%{ // // RELAX NG Compact Syntax parser // // Author: // Atsushi Enomoto // // (C)2003 Atsushi Enomoto // // Copyright (c) 2004 Novell Inc. // All rights reserved // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System.Collections.Specialized; using System.IO; using System.Xml; using Commons.Xml.Relaxng; namespace Commons.Xml.Relaxng.Rnc { public class RncParser { public static RelaxngPattern ParseRnc (TextReader reader) { return ParseRnc (reader, new NameTable ()); } public static RelaxngPattern ParseRnc (TextReader reader, XmlNameTable nameTable) { return ParseRnc (reader, nameTable, null); } public static RelaxngPattern ParseRnc (TextReader reader, XmlNameTable nameTable, string baseUri) { return ParseRnc (reader, nameTable, baseUri, null); } public static RelaxngPattern ParseRnc (TextReader reader, XmlNameTable nameTable, string baseUri, string defaultNamespace) { return new RncParser (nameTable).Parse (reader, baseUri, defaultNamespace); } XmlNamespaceManager nsmgr; XmlNamespaceManager dtnsmgr; string defaultNamespace; static int yacc_verbose_flag; RncTokenizer tokenizer; public RncParser (XmlNameTable nameTable) { if (nameTable == null) nameTable = new NameTable (); nsmgr = new XmlNamespaceManager (nameTable); dtnsmgr = new XmlNamespaceManager (nameTable); dtnsmgr.AddNamespace ("xsd", "http://www.w3.org/2001/XMLSchema-datatypes"); ErrorOutput = System.IO.TextWriter.Null; } public int Line { get { return tokenizer.Line; } } public int Column { get { return tokenizer.Column; } } public string BaseUri { get { return tokenizer.BaseUri; } } // note that this is different notion than that of xmlns. public RelaxngPattern Parse (TextReader source) { return Parse (source, null); } public RelaxngPattern Parse (TextReader source, string baseUri) { return Parse (source, baseUri, null); } public RelaxngPattern Parse (TextReader source, string baseUri, string defaultNamespace) { this.defaultNamespace = defaultNamespace ?? string.Empty; if (defaultNamespace != null && defaultNamespace.Length != 0) nsmgr.AddNamespace (String.Empty, defaultNamespace); try { if (Environment.GetEnvironmentVariable ("MONO_RELAXNG_COMPACT_DEBUG") == "yes") debug = new yydebug.yyDebugSimple (); tokenizer = new RncTokenizer (source, baseUri); RelaxngPattern p = (RelaxngPattern) yyparse (tokenizer); if (p is RelaxngGrammar) ((RelaxngGrammar) p).IsSourceCompactSyntax = true; return p; } catch (Exception ex) { throw new RelaxngException (String.Format ("Tokenizer error at line {0}, column {1}: {2}", Line, Column, ex.Message), ex); } } private void FillLocation (RelaxngElementBase el) { el.BaseUri = BaseUri; el.LineNumber = Line; el.LinePosition = Column; } private void FillGrammarContent (IList source, IList starts, IList defines, IList divs, IList includes) { foreach (RelaxngElementBase elem in source) { if (elem is RelaxngStart) starts.Add (elem); else if (elem is RelaxngDefine) defines.Add (elem); else if (elem is RelaxngDiv) divs.Add (elem); else if (elem is RelaxngInclude) includes.Add (elem); else throw new InvalidOperationException (); } } private XmlQualifiedName SplitQName (XmlNamespaceManager nsmgr, string name) { int colon = name.IndexOf (':'); if (colon < 0) return new XmlQualifiedName (name, String.Empty); string local = name.Substring (colon + 1); string prefix = name.Substring (0, colon); return new XmlQualifiedName (local, nsmgr.LookupNamespace (nsmgr.NameTable.Get (prefix))); } private void FillElementDefaultNS (RelaxngNameClass nc) { RelaxngName name = nc as RelaxngName; if (name != null) { if (name.Namespace == null) name.Namespace = defaultNamespace; return; } RelaxngNameChoice choice = nc as RelaxngNameChoice; if (choice != null) { foreach (RelaxngNameClass c in choice.Children) FillElementDefaultNS (c); } } private void FillAttributeDefaultNS (RelaxngNameClass nc) { RelaxngName name = nc as RelaxngName; if (name != null) { if (name.Namespace == null) name.Namespace = String.Empty; return; } RelaxngNameChoice choice = nc as RelaxngNameChoice; if (choice != null) { foreach (RelaxngNameClass c in choice.Children) FillAttributeDefaultNS (c); } } %} %token ERROR %token EOF %token KeywordAttribute "attribute" %token KeywordDefault //"default" %token KeywordDatatypes "datatypes" %token KeywordDiv "div" %token KeywordElement "element" %token KeywordEmpty "empty" %token KeywordExternal "external" %token KeywordGrammar "grammar" %token KeywordInclude "include" %token KeywordInherit "inherit" %token KeywordList "list" %token KeywordMixed "mixed" %token KeywordNamespace //"namespace" %token KeywordNotAllowed "notAllowed" %token KeywordParent "parent" %token KeywordStart "start" %token KeywordString //"string" %token KeywordText "text" %token KeywordToken "left" %token Equal "=" %token Comma "," %token Tilde "~" %token OpenCurly "{" %token CloseCurly "}" %token OpenParen "(" %token CloseParen ")" %token OpenBracket "[" %token CloseBracket "]" %token Amp "&" %token Bar "|" %token Question "?" %token Asterisk "*" %token Plus "+" %token Minus "-" %token OrEquals "|=" %token AndEquals "&=" %token TwoGreaters ">>" %token LiteralSegment %token NCName %token QuotedIdentifier %token Documentation /* These tokens are parsed by RncTokenizer, since whitespaces between the particles are not allowed. */ %token NCName %token CName %token NsName %start TopLevel %% TopLevel /* returns RelaxngPattern */ : Preamble TopLevelBody { $$ = (RelaxngPattern) $2; } ; Preamble /* returns null */ : /* empty */ { $$ = null; } | Decl Preamble { $$ = null; } ; Decl /* returns null */ : KeywordNamespace NamespacePrefix Equal NamespaceURILiteral { // TODO: constraints string prefix = (string) $2; string ns = (string) $4; if (prefix == "local") nsmgr.AddNamespace (String.Empty, ns); else nsmgr.AddNamespace (prefix, ns); $$ = null; } | KeywordDefault KeywordNamespace Equal NamespaceURILiteral { // TODO: constraints string ns = (string) $4; defaultNamespace = ns; nsmgr.AddNamespace (String.Empty, ns); $$ = null; } | KeywordDefault KeywordNamespace NamespacePrefix Equal NamespaceURILiteral { // TODO: constraints string prefix = (string) $3; string ns = (string) $5; defaultNamespace = ns; nsmgr.AddNamespace (String.Empty, ns); nsmgr.AddNamespace (prefix, ns); $$ = null; } | KeywordDatatypes DatatypePrefix Equal Literal { // TODO: constraints string prefix = (string) $2; string ns = (string) $4; dtnsmgr.AddNamespace (prefix, ns); $$ = null; } ; NamespacePrefix /* returns string */ : IdentifierOrKeyword { $$ = (string) $1; } ; DatatypePrefix /* returns string */ : IdentifierOrKeyword { $$ = (string) $1; } ; NamespaceURILiteral /* returns string */ : Literal { $$ = (string) $1; } | KeywordInherit { $$ = defaultNamespace; } ; TopLevelBody /* returns RelaxngPattern */ : Pattern { // TODO: Constraint: single element // IList pl = (IList) $1; // if (pl.Count != 1) // throw new RelaxngException ("The number of the top level pattern must be exactly one."); // $$ = pl [0]; $$ = (RelaxngPattern) $1; } | Grammar { RelaxngGrammar g = new RelaxngGrammar (); FillLocation (g); if (defaultNamespace != null) g.DefaultNamespace = defaultNamespace; RelaxngGrammarContentList list = (RelaxngGrammarContentList) $1; FillGrammarContent (list, g.Starts, g.Defines, g.Divs, g.Includes); $$ = g; } ; Grammar /* returns RelaxngGrammarContentList */ : /* empty */ { $$ = new RelaxngGrammarContentList (); } | Member Grammar { RelaxngGrammarContentList al = (RelaxngGrammarContentList) $2; if ($1 != null) al.Insert (0, (IGrammarContent) $1); $$ = al; } ; Member /* returns nullable IGrammarContent (RelaxngDiv, RelaxngInclude, RelaxngStart, RelaxngDefine) */ : AnnotatedComponent { $$ = (IGrammarContent) $1; } | AnnotationElementNotKeyword { $$ = null; } ; AnnotatedComponent /* returns IGrammarContent */ : Annotations Component { // $$ = ApplyAnnotations ((string) $1, (RelaxngElementBase) $2); $$ = (IGrammarContent) $2; } ; Component /* returns IGrammarContent */ : Start { $$ = (RelaxngStart) $1; } | Define { $$ = (RelaxngDefine) $1; } | Include { $$ = (RelaxngInclude) $1; } | Div { $$ = (RelaxngDiv) $1; } ; Start /* returns RelaxngStart */ : KeywordStart AssignOp Pattern { RelaxngStart start = new RelaxngStart (); FillLocation (start); start.Combine = (string) $2; start.Pattern = (RelaxngPattern) $3; $$ = start; } ; Define /* returns RelaxngDefine */ : Identifier AssignOp Pattern { RelaxngDefine def = new RelaxngDefine (); FillLocation (def); def.Name = (string) $1; def.Combine = (string) $2; def.Patterns.Add ((RelaxngPattern) $3); $$ = def; } ; AssignOp /* returns string */ : Equal { $$ = null; } | OrEquals { $$ = "choice"; } | AndEquals { $$ = "interleave"; } ; Include /* returns RelaxngInclude */ : KeywordInclude AnyURILiteral OptInherit OptIncludeBody { // FIXME: OptInherit is not handled properly. RelaxngInclude include = new RelaxngInclude (); FillLocation (include); include.Href = (string) $2; include.NSContext = (string) $3; FillGrammarContent ((IList) $4, include.Starts, include.Defines, include.Divs, null); $$ = include; } ; AnyURILiteral /* returns string */ : Literal { // Constraints: any URI $$ = (string) $1; } ; OptInherit /* returns string */ /* The empty value will be handled at Compile() time. */ : /* empty */ { // MakeNsAttribute (LookupDefault (environment)); $$ = defaultNamespace; } | KeywordInherit Equal IdentifierOrKeyword { // MakeNsAttribute (LookupPrefix (environment, $3)); $$ = nsmgr.LookupPrefix ((string) $3); } ; OptIncludeBody /* returns IList */ : /* empty */ { $$ = new ArrayList (); } | OpenCurly IncludeBody CloseCurly { $$ = (IList) $2; } ; IncludeBody /* returns IList */ : /* empty */ { $$ = new ArrayList (); } | IncludeMember IncludeBody { ArrayList al = (ArrayList) $2; al.Insert (0, $1); $$ = al; } ; IncludeMember /* returns RelaxngElementBase */ : AnnotatedIncludeComponent { $$ = (RelaxngElementBase) $1; } | AnnotationElementNotKeyword { $$ = (RelaxngElementBase) $1; } ; AnnotatedIncludeComponent /* returns IGrammarContent */ : Annotations IncludeComponent { // $$ = ApplyAnnotations ((string) $1, (RelaxngElementBase) $2); $$ = (IGrammarContent) $2; } ; IncludeComponent /* returns IGrammarContent */ : Start { $$ = (RelaxngStart) $1; } | Define { $$ = (RelaxngDefine) $1; } | IncludeDiv { $$ = (RelaxngDiv) $1; } ; Div /* returns RelaxngDiv */ : KeywordDiv OpenCurly Grammar CloseCurly { RelaxngDiv div = new RelaxngDiv (); FillLocation (div); FillGrammarContent ((IList) $3, div.Starts, div.Defines, div.Divs, div.Includes); $$ = div; } ; IncludeDiv /* returns RelaxngDiv */ : KeywordDiv OpenCurly IncludeBody CloseCurly { RelaxngDiv div = new RelaxngDiv (); FillLocation (div); FillGrammarContent ((IList) $3, div.Starts, div.Defines, div.Divs, div.Includes); $$ = div; } ; Pattern /* returns RelaxngPattern */ : InnerPattern ; InnerPattern /* returns RelaxngPattern */ /* TODO: applyAnnotations() are omitted */ : InnerParticle { $$ = (RelaxngPattern) $1; } | ParticleChoice { RelaxngPatternList list = (RelaxngPatternList) $1; RelaxngChoice choice = new RelaxngChoice (); FillLocation (choice); for (int i = 0; i < list.Count; i++) choice.Patterns.Add (list [i]); // This is said as to return Elements, while ApplyAnnotations() is said to return Element $$ = choice; } | ParticleGroup { RelaxngPatternList list = (RelaxngPatternList) $1; RelaxngGroup group = new RelaxngGroup (); FillLocation (group); for (int i = 0; i < list.Count; i++) group.Patterns.Add (list [i]); // This is said as to return Elements, while ApplyAnnotations() is said to return Element $$ = group; } | ParticleInterleave { RelaxngPatternList list = (RelaxngPatternList) $1; RelaxngInterleave interleave = new RelaxngInterleave (); FillLocation (interleave); for (int i = 0; i < list.Count; i++) interleave.Patterns.Add (list [i]); // This is said as to return Elements, while ApplyAnnotations() is said to return Element $$ = interleave; } | AnnotatedDataExcept { $$ = (RelaxngData) $1; } ; ParticleChoice /* returns RelaxngPatternList */ : Particle Bar Particle { RelaxngPatternList list = new RelaxngPatternList (); list.Add ((RelaxngPattern) $1); list.Add ((RelaxngPattern) $3); $$ = list; } | Particle Bar ParticleChoice { RelaxngPatternList list = (RelaxngPatternList) $3; list.Insert (0, (RelaxngPattern) $1); $$ = list; } ; ParticleGroup /* returns RelaxngPatternList */ : Particle Comma Particle { RelaxngPatternList list = new RelaxngPatternList (); list.Add ((RelaxngPattern) $1); list.Add ((RelaxngPattern) $3); $$ = list; } | Particle Comma ParticleGroup { RelaxngPatternList list = (RelaxngPatternList) $3; list.Insert (0, (RelaxngPattern) $1); $$ = list; } ; ParticleInterleave /* returns RelaxngPatternList */ : Particle Amp Particle { RelaxngPatternList list = new RelaxngPatternList (); list.Add ((RelaxngPattern) $1); list.Add ((RelaxngPattern) $3); $$ = list; } | Particle Amp ParticleInterleave { RelaxngPatternList list = (RelaxngPatternList) $3; list.Insert (0, (RelaxngPattern) $1); $$ = list; } ; Particle /* returns RelaxngPattern */ : InnerParticle ; InnerParticle /* returns RelaxngPattern */ : AnnotatedPrimary { // $$ = ApplyAnnotationsGroup (null, (RelaxngPatternList) $1); $$ = $1; } | RepeatedPrimary FollowAnnotations { // FIXME: annotations are not handled RelaxngPattern p = (RelaxngPattern) $1; // RelaxngPatternList l = new RelaxngPatternList (); // l.Add (p); // $$ = l; $$ = p; } ; RepeatedPrimary /* returns RelaxngPattern */ : AnnotatedPrimary Asterisk { RelaxngZeroOrMore zom = new RelaxngZeroOrMore (); FillLocation (zom); zom.Patterns.Add ((RelaxngPattern) $1); $$ = zom; } | AnnotatedPrimary Plus { RelaxngOneOrMore oom = new RelaxngOneOrMore (); FillLocation (oom); oom.Patterns.Add ((RelaxngPattern) $1); $$ = oom; } | AnnotatedPrimary Question { RelaxngOptional opt = new RelaxngOptional (); FillLocation (opt); opt.Patterns.Add ((RelaxngPattern) $1); $$ = opt; } ; AnnotatedPrimary /* returns RelaxngPattern */ : LeadAnnotatedPrimary FollowAnnotations { // FIXME: handle followAnnotations $$ = $1; } ; AnnotatedDataExcept /* returns RelaxngPattern */ : LeadAnnotatedDataExcept FollowAnnotations { // FIXME: handle followAnnotations $$ = $1; } ; LeadAnnotatedDataExcept /* returns RelaxngData */ : Annotations DataExcept { $$ = $2; } ; LeadAnnotatedPrimary /* returns RelaxngPattern */ : Annotations Primary { // LAMESPEC: This should return Elements, while ApplyAnnotations() returns Element // RelaxngPatternList list = new RelaxngPatternList (); // list.Add ((RelaxngPattern) ApplyAnnotations ((string) $1, (RelaxngPattern) $2)); // $$ = list; $$ = (RelaxngPattern) $2; } | Annotations OpenParen InnerPattern CloseParen { // $$ = (RelaxngPatternList) $3; $$ = (RelaxngPattern) $3; } ; Primary /* returns RelaxngPattern */ : KeywordElement NameClass OpenCurly Pattern CloseCurly { RelaxngNameClass nc = (RelaxngNameClass) $2; RelaxngElement el = new RelaxngElement (); FillLocation (el); el.NameClass = nc; FillElementDefaultNS (el.NameClass); el.Patterns.Add ((RelaxngPattern) $4); $$ = el; } | KeywordAttribute NameClass OpenCurly Pattern CloseCurly { RelaxngNameClass nc = (RelaxngNameClass) $2; RelaxngAttribute attr = new RelaxngAttribute (); FillLocation (attr); attr.NameClass = nc; FillAttributeDefaultNS (attr.NameClass); attr.Pattern = (RelaxngPattern) $4; $$ = attr; } | KeywordMixed OpenCurly Pattern CloseCurly { RelaxngMixed mixed = new RelaxngMixed (); FillLocation (mixed); mixed.Patterns.Add ((RelaxngPattern) $3); $$ = mixed; } | KeywordList OpenCurly Pattern CloseCurly { RelaxngList list = new RelaxngList (); FillLocation (list); list.Patterns.Add ((RelaxngPattern) $3); $$ = list; } | DatatypeName OptParams { RelaxngData data = new RelaxngData (); FillLocation (data); XmlQualifiedName dtName = (XmlQualifiedName) $1; data.DatatypeLibrary = dtName.Namespace; data.Type = dtName.Name; foreach (RelaxngParam p in (ICollection) $2) data.ParamList.Add (p); $$ = data; } | DatatypeName DatatypeValue { RelaxngValue value = new RelaxngValue (); FillLocation (value); XmlQualifiedName dtName = (XmlQualifiedName) $1; if (dtName.Namespace != RelaxngGrammar.NamespaceURI) value.DatatypeLibrary = dtName.Namespace; value.Type = dtName.Name; value.Value = (string) $2; $$ = value; } | DatatypeValue { RelaxngValue value = new RelaxngValue (); FillLocation (value); value.Value = (string) $1; // RELAX NG default type value.Type = "string"; value.DatatypeLibrary = String.Empty; $$ = value; } | KeywordEmpty { RelaxngEmpty empty = new RelaxngEmpty (); FillLocation (empty); $$ = empty; } | KeywordNotAllowed { RelaxngNotAllowed na = new RelaxngNotAllowed (); FillLocation (na); $$ = na; } | KeywordText { RelaxngText text = new RelaxngText (); FillLocation (text); $$ = text; } | Ref { RelaxngRef r = new RelaxngRef (); FillLocation (r); r.Name = (string) $1; $$ = r; } | KeywordParent Ref { RelaxngParentRef pref = new RelaxngParentRef (); FillLocation (pref); pref.Name = (string) $2; $$ = pref; } | KeywordGrammar OpenCurly Grammar CloseCurly { RelaxngGrammar g = new RelaxngGrammar (); FillLocation (g); FillGrammarContent ((IList) $3, g.Starts, g.Defines, g.Divs, g.Includes); $$ = g; } | KeywordExternal AnyURILiteral OptInherit { RelaxngExternalRef extref = new RelaxngExternalRef (); FillLocation (extref); extref.Href = (string) $2; extref.NSContext = (string) $3; $$ = extref; } ; DataExcept /* returns RelaxngData */ : DatatypeName OptParams Minus LeadAnnotatedPrimary { XmlQualifiedName type = (XmlQualifiedName) $1; RelaxngData data = new RelaxngData (); FillLocation (data); data.Type = type.Name; data.DatatypeLibrary = type.Namespace; foreach (RelaxngParam p in (RelaxngParamList) $2) data.ParamList.Add (p); data.Except = new RelaxngExcept (); FillLocation (data.Except); data.Except.Patterns.Add ((RelaxngPattern) $4); $$ = data; } ; Ref /* returns string */ : Identifier ; DatatypeName : CName { string cname = (string) $1; $$ = SplitQName (dtnsmgr, cname); } | KeywordString { $$ = new XmlQualifiedName ("string", String.Empty); } | KeywordToken { $$ = new XmlQualifiedName ("token", String.Empty); } ; DatatypeValue : Literal ; OptParams : /* empty */ { $$ = new RelaxngParamList (); } | OpenCurly Params CloseCurly { $$ = $2; } ; Params : /* empty */ { $$ = new RelaxngParamList (); } | Param Params { RelaxngParamList al = (RelaxngParamList) $2; al.Insert (0, (RelaxngParam) $1); $$ = al; } ; Param /* returns RelaxngParam */ : Annotations IdentifierOrKeyword Equal Literal { RelaxngParam prm = new RelaxngParam (); FillLocation (prm); prm.Name = (string) $2; prm.Value = (string) $4; // $$ = ApplyAnnotations ((string) $1, prm); $$ = prm; } ; NameClass /* returns RelaxngNameClass */ : InnerNameClass { $$ = $1; } ; InnerNameClass /* returns RelaxngNameClass */ : AnnotatedSimpleNameClass { $$ = (RelaxngNameClass) $1; } | NameClassChoice { RelaxngNameChoice cho = new RelaxngNameChoice (); FillLocation (cho); RelaxngNameClassList list = (RelaxngNameClassList) $1; for (int i = 0; i < list.Count; i++) cho.Children.Add ((RelaxngNameClass) list [i]); $$ = cho; } | AnnotatedExceptNameClass { $$ = (RelaxngNameClass) $1; } ; NameClassChoice /* returns RelaxngNameClassList */ : AnnotatedSimpleNameClass Bar AnnotatedSimpleNameClass { RelaxngNameClassList list = new RelaxngNameClassList (); list.Add ((RelaxngNameClass) $1); list.Add ((RelaxngNameClass) $3); $$ = list; } | AnnotatedSimpleNameClass Bar NameClassChoice { RelaxngNameClassList list = (RelaxngNameClassList) $3; list.Insert (0, (RelaxngNameClass) $1); $$ = list; } ; AnnotatedExceptNameClass /* returns RelaxngNameClass */ : LeadAnnotatedExceptNameClass FollowAnnotations { $$ = (RelaxngNameClass) $1; } ; LeadAnnotatedExceptNameClass /* returns RelaxngNameClass */ : Annotations ExceptNameClass { $$ = (RelaxngNameClass) $2; } ; AnnotatedSimpleNameClass /* returns RelaxngNameClass */ : LeadAnnotatedSimpleNameClass FollowAnnotations { // FIXME: annotations $$ = $1; } ; LeadAnnotatedSimpleNameClass /* returns RelaxngNameClass */ : Annotations SimpleNameClass { // FIXME: applyAnnotations $$ = (RelaxngNameClass) $2; } | Annotations OpenParen InnerNameClass CloseParen { $$ = $3; } ; ExceptNameClass : NsName Minus LeadAnnotatedSimpleNameClass { RelaxngNsName nsName = new RelaxngNsName (); FillLocation (nsName); nsName.Namespace = nsmgr.LookupNamespace ((string) $1); nsName.Except = new RelaxngExceptNameClass (); FillLocation (nsName.Except); nsName.Except.Names.Add ((RelaxngNameClass) $3); $$ = nsName; } | Asterisk Minus LeadAnnotatedSimpleNameClass { RelaxngAnyName anyName = new RelaxngAnyName (); FillLocation (anyName); anyName.Except = new RelaxngExceptNameClass (); FillLocation (anyName.Except); anyName.Except.Names.Add ((RelaxngNameClass) $3); $$ = anyName; } ; SimpleNameClass /* returns RelaxngNameClass */ : IdentifierOrKeyword { RelaxngName name = new RelaxngName (); FillLocation (name); name.LocalName = (string) $1; name.Namespace = null; $$ = name; } | CName { string cname = (string) $1; XmlQualifiedName qname = SplitQName (nsmgr, cname); RelaxngName name = new RelaxngName (); FillLocation (name); name.LocalName = qname.Name; name.Namespace = qname.Namespace; $$ = name; } | NsName { RelaxngNsName nsName = new RelaxngNsName (); FillLocation (nsName); nsName.Namespace = nsmgr.LookupNamespace ((string) $1); $$ = nsName; } | Asterisk { RelaxngAnyName anyName= new RelaxngAnyName (); FillLocation (anyName); $$ = anyName; } ; FollowAnnotations : /* empty */ { $$ = null; } | TwoGreaters AnnotationElement FollowAnnotations { // FIXME: handle them $$ = null; } ; Annotations /* returns null */ /* FIXME: needed to handle them? */ : Documentations { $$ = null; } | Documentations OpenBracket AnnotationContentInAnnotations CloseBracket { $$ = null; } ; // This one is extra to the original syntax rule. Also it and following // annotation related rules are modified to work fine without ambiguity. // FIXME: it should reject attributes after elements... AnnotationContentInAnnotations : // empty | PrefixedName Equal Literal AnnotationContentInAnnotations | PrefixedName AnnotationAttributesContent AnnotationContentInAnnotations | IdentifierOrKeyword AnnotationAttributesContent AnnotationContentInAnnotations ; // ... but something like this one should be used instead. AttributableAnnotations : // empty | AttributableAnnotations PrefixedName Equal Literal NonAttributableAnnotations ; NonAttributableAnnotations : // empty | PrefixedName AnnotationAttributesContent | NonAttributableAnnotations IdentifierOrKeyword AnnotationAttributesContent ; AnnotationElement : ForeignElementName AnnotationAttributesContent { // do nothing // $$ = Element ($1, $2); $$ = null; } ; ForeignElementName : IdentifierOrKeyword { $$ = new XmlQualifiedName ((string) $1, String.Empty); } | PrefixedName // Constraint: RELAX NG namespace URI ; // FIXME: due to syntax ambiguity it cannot be included in the creation rules. AnnotationElementNotKeyword /* null */ : ERROR ; /* AnnotationElementNotKeyword // null : ForeignElementNameNotKeyword AnnotationAttributeContent { // do nothing $$ = $1; } ; ForeignElementNameNotKeyword // QName : Identifier { $$ = new XmlQualifiedName ((string) $1, String.Empty); } | PrefixedName { // Constraint: RELAX NG namespace URI $$ = (XmlQualifiedName) $1; } ; */ AnnotationAttributesContent /* returns null */ : OpenBracket NestedAnnotationContents CloseBracket { $$ = null; } ; // ditto (see also AnnotationContentInAnnotations) NestedAnnotationContents : /* empty */ | PrefixedName Equal Literal NestedAnnotationContents | IdentifierOrKeyword Equal Literal NestedAnnotationContents | PrefixedName AnnotationAttributesContent NestedAnnotationContents | IdentifierOrKeyword AnnotationAttributesContent NestedAnnotationContents | Literal | Literal NestedAnnotationContents ; NestedAnnotationAttributes /* returns null */ : /* empty */ { $$ = null; } | AnyAttributeName Equal Literal NestedAnnotationAttributes { // Constraint: duplicate attributes // do nothing // $$ = Attribute ($1, $2); $$ = null; } AnyAttributeName /* returns XmlQualifiedName */ : IdentifierOrKeyword { $$ = new XmlQualifiedName ((string) $1); } | PrefixedName { // Constraint: xmlns namespace URI $$ = (XmlQualifiedName) $1; } ; AnnotationContent /* returns null */ : /* empty */ { $$ = null; } | NestedAnnotationElement AnnotationContent { $$ = null; } | Literal AnnotationContent { $$ = null; } ; NestedAnnotationElement /* returns null */ : AnyElementName AnnotationAttributesContent { // do nothing // $$ = Element ($1, $2); $$ = null; } ; AnyElementName /* returns XmlQualifiedName */ : IdentifierOrKeyword { $$ = new XmlQualifiedName ((string) $1, String.Empty); } | PrefixedName { $$ = (XmlQualifiedName) $1; } ; PrefixedName /* returns XmlQualifiedName */ : CName { // Constraint: annotation inherit $$ = SplitQName (nsmgr, (string) $1); } ; Documentations /* returns null */ : /* empty */ { $$ = null; } | Documentation Documentations { // do nothing // $$ = Element (DocumentationElementName (), Text ((string) $1), $2); $$ = null; } ; IdentifierOrKeyword /* returns string */ : Identifier { $$ = (string) $1; } | Keyword { $$ = (string) $1; } ; Keyword /* returns string */ : KeywordAttribute | KeywordDefault | KeywordDatatypes | KeywordDiv | KeywordElement | KeywordEmpty | KeywordExternal | KeywordGrammar | KeywordInclude | KeywordInherit | KeywordList | KeywordMixed | KeywordNamespace | KeywordNotAllowed | KeywordParent | KeywordStart | KeywordString | KeywordText | KeywordToken ; Literal /* returns string */ : LiteralSegment { $$ = (string) $1; } | LiteralSegment Tilde Literal { $$ = (string) $1 + (string) $3; } ; Identifier /* returns string */ : NCName { $$ = (string) $1; } | QuotedIdentifier { $$ = (string) $1; } ; %% }