1: // Reference ETL Parser for Java
     2: // Copyright (c) 2000-2007 Constantine A Plotnikov
     3: //
     4: // Permission is hereby granted, free of charge, to any person 
     5: // obtaining a copy of this software and associated documentation 
     6: // files (the "Software"), to deal in the Software without restriction,
     7: // including without limitation the rights to use, copy, modify, merge, 
     8: // publish, distribute, sublicense, and/or sell copies of the Software, 
     9: // and to permit persons to whom the Software is furnished to do so, 
    10: // subject to the following conditions:
    11: //
    12: // The above copyright notice and this permission notice shall be 
    13: // included in all copies or substantial portions of the Software.
    14: // 
    15: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    16: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    17: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    18: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
    19: // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
    20: // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
    21: // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    22: // SOFTWARE. 
    23: doctype public "-//IDN etl.sf.net//ETL//Grammar 0.2.1";
    24: /// This is a legacy grammar for 0.2.0 syntax defined using 0.2.1 syntax.
    25: /// It is used in grammar update script.
    26: ///
    27: /// This is a definition for the grammar language itself.
    28: /// This grammar is actually used for parsing other grammars. 
    29: /// The text of this specific grammar itself is parsed using bootstrap 
    30: /// parser, then the grammar is compiled using normal grammar compilation 
    31: /// path.
    32: ///
    33: /// The parsing model is AST building. The parser tries to match syntax 
    34: /// constructs and creates AST according to specified AST constructs. 
    35: /// AST assumes to contains objects and properties. So AST is directly 
    36: /// mappable to object models like JavaBeans, EMOF, MOF 1.2, and EMF.
    37: /// 
    38: /// Properties are identified by name and objects are identified by 
    39: /// namespace URI and name. The object identification idea is borrowed from XMI
    40: /// and it is even possible to generate XMI-file without prior knowledge of 
    41: /// metamodel.
    42: ///
    43: /// There are two kinds of syntax constructs: expressions and statements.
    44: ///
    45: /// Expression model is borrowed from prolog. Operator has been borrowed from
    46: /// Prolog almost as is. Each operator has priority and associativity. 
    47: /// Associativity has format "AfA" where A can be "x" or "y", "y" matches 
    48: /// expression of the same priority and "x" matches expression of lesser 
    49: /// priority. For example yfx operator is "+" and "-" from C, x+y-z is parsed 
    50: /// as (x+y)-y. Example of  xfy operator is assignment operator from C. a=b=c 
    51: /// is parsed as a=(b=c).
    52: ///
    53: /// Note that yfy are not supported yet. You have to choose between yfx or xfy,
    54: ///
    55: /// Also "f" operators have special semantics, they appear on level 0 and 
    56: /// are primary operators. They can have neither left nor right part.
    57: ///
    58: /// Operators can be simple or composite. Simple operators have just a token 
    59: /// specified. See definition of "|" and "?" operators in this this grammar.
    60: /// Composite operators allow more complex syntax constructs. Composite 
    61: /// operators are used define primary level of the grammar. However they can
    62: /// be used to specify non primary operators too. Java method invocation and
    63: /// array access operators are examples of this. Composite operator can use
    64: /// all syntax expressions used in statements.
    65: ///
    66: /// Statement defines content of segment returned from term parser. The statement
    67: /// is defined using generic constructs like sections, lists, and choice, and 
    68: /// and tokens.
    69: /// 
    70: /// <author>const</author>
    71: grammar net.sf.etl.grammars.Grammar {
    72: 	namespace g = "http://etl.sf.net/etl/grammar/0.2.0";
    73: 	
    74: 	/// This abstract context contains definition used across this grammar. 
    75: 	context abstract Base {
    76: 		
    77: 		/// String token definition
    78: 		def String {
    79: 			string(quote="\"") | string(quote='\'');
    80: 		};
    81: 
    82: 		/// Documentation mapping definition. This mapping is used 
    83: 		/// by all statements in the grammar.
    84: 		documentation Documentation {
    85: 			@ documentation += doclines wrapper g:DocumentationLine.text;
    86: 		};		
    87: 
    88: 		/// Definition of object name expression. This reusable fragment
    89: 		/// is used in places where object name is required.
    90: 		def ObjectNameDef {
    91: 			^ g:ObjectName {
    92: 				@ prefix = identifier;
    93: 				% : {
    94: 					@ name = identifier;
    95: 				};
    96: 			};
    97: 		};
    98: 
    99: 		/// Definition for wrapper section fragment. 
   100: 		def WrapperDef {
   101: 			% wrapper {
   102: 				ref(WrapperObject);
   103: 			};
   104: 		};
   105: 
   106: 		/// Definition for wrapper specification fragment. Wrapper is
   107: 		/// is usually attached to tokens. When token matches, its value
   108: 		/// wrapped into specified object and property.
   109: 		def WrapperObject {
   110: 			^ g:Wrapper {
   111: 				@ object = ref(ObjectNameDef);
   112: 				% . {
   113: 					@ property = identifier;
   114: 				};
   115: 			};
   116: 		};
   117: 	};
   118: 
   119: 
   120: 	
   121: 	/// This is base mapping syntax context. Mapping context might
   122: 	/// contain blank statements and let statements.
   123: 	context abstract BaseMappingSyntax {
   124: 		include Base;
   125: 
   126: 		/// Let statement. It is used to define mapping from syntax 
   127: 		/// to property of the object. The statement matches expression
   128: 		/// after "=" or "+=". All objects or values that are encountered
   129: 		/// in the property are assigned to property of top object specified 
   130: 		/// by name property.
   131: 		///
   132: 		/// The "+=" version assumes list property, the "=" version assumes 
   133: 		/// property with upper multiplicity equal to 1.
   134: 		statement Let {
   135: 			^ g:Let {
   136: 				% let {
   137: 					@ name = identifier;
   138: 					@ operator = token(+=) | token(=);
   139: 					@ expression = expression;
   140: 				};
   141: 			};
   142: 		};
   143: 		
   144: 		/// This is blank statement. It is used to attach attributes 
   145: 		/// and documentation comments. This is may be used for example
   146: 		/// for attaching annotations after last statement.
   147: 		statement BlankStatement {
   148: 			^ g:BlankSyntaxStatement {
   149: 			};
   150: 		};
   151: 	};
   152: 
   153: 	/// This is base syntax context. This context might contain object
   154: 	/// specification in addition to let statement.
   155: 	context abstract BaseSyntax {
   156: 		include BaseMappingSyntax;
   157: 
   158: 		/// Utility definition used in different parts of the syntax
   159: 		def SequenceDef  {
   160: 			^ g:Sequence {
   161: 				@ syntax += block;
   162: 			};
   163: 		};
   164: 
   165: 		/// Object expression. It is used to specify context of parsing. 
   166: 		/// 
   167: 		/// The expression matches its content, and creates an context object
   168: 		/// all properties that are directly or indirectly specified in the 
   169: 		/// content will be assumed to be specified in context of this object
   170: 		/// unless new object directive is encountered.
   171: 		///
   172: 		/// It is an error to specify value or object generators inside object
   173: 		/// whithout property layer.
   174: 		op composite Object(f) {
   175: 			^ g:ObjectOp {
   176: 				% object {
   177: 					@ name = ref(ObjectNameDef);
   178: 					@ syntax = ref(SequenceDef);
   179: 				};
   180: 			};
   181: 		};
   182: 	};
   183: 
   184: 
   185: 	/// This is base syntax context. 
   186: 	context abstract BaseCompositeSyntax {
   187: 		include BaseSyntax;
   188: 		
   189: 		/// Expression statement. This statement is a container for expression.
   190: 		/// The statement has the same semantics as expression contained in it.
   191: 		statement Expression {
   192: 			^ g:ExpressionStatement {
   193: 				@ syntax = expression;
   194: 			};
   195: 		};
   196: 		
   197: 		
   198: 	};
   199: 
   200: 
   201: 	/// This syntax is used inside documentation statement. 
   202: 	context DocumentationSyntax {
   203: 		include BaseMappingSyntax;
   204: 		/// This is doclines expression. It matches sequence of documentation lines.
   205: 		/// <example>
   206: 		/// 	let documentation += doclines wrapper xj:DocumentationLine.text;
   207: 		/// </example>
   208: 		op composite Doclines(f) {
   209: 			^ g:DocLinesOp {
   210: 				% doclines {
   211: 					@ wrapper = ref(WrapperDef)?;
   212: 				};
   213: 			};
   214: 		};
   215: 	};	
   216: 
   217: 	/// This context specifies syntax for simple operations
   218: 	context SimpleOpSyntax {
   219: 		include BaseCompositeSyntax;
   220: 		
   221: 		/// This expression matches left operand in expression. It is used
   222: 		/// in let expression to specify property to which left operand 
   223: 		/// of operator should be assigned.
   224: 		op composite Left(f) {
   225: 			^ g:OperandOp {
   226: 				@ position = token(left);
   227: 			};
   228: 		};
   229: 		
   230: 		/// This expression matches right operand in expression. It is used
   231: 		/// in let expression to specify property to which right operand 
   232: 		/// of operator should be assigned.
   233: 		op composite Right(f) {
   234: 			^ g:OperandOp {
   235: 				@ position = token(right);
   236: 			};
   237: 		};
   238: 	};
   239: 	
   240: 	/// This context contains definition of primitive syntax operators
   241: 	context abstract CompositeOperatorsSyntax {
   242: 		include BaseCompositeSyntax;
   243: 
   244: 		
   245: 		/// Choice operator. It matches one of two alternatives.
   246: 		op ChoiceOp(xfy,300,|) {
   247: 			^ g:ChoiceOp { @ options += left; @ options += right; };
   248: 		};
   249: 
   250: 		/// First choice operator. It tries to match the first 
   251: 		/// alternative than the second one.
   252: 		op FirstChoiceOp(xfy,200,/) {
   253: 			^ g:FirstChoiceOp { @ first = left; @ second = right; };
   254: 		};
   255: 
   256: 
   257: 		/// This operator matches empty sequence of tokens or its operand.
   258: 		op OptionalOp(yf,100,?) {
   259: 			^ g:OptionalOp { @ syntax = left; };
   260: 		};
   261: 		
   262: 		/// This operator matches non empty sequence of specified operand.
   263: 		op OneOrMoreOp(yf,100,+) {
   264: 			^ g:OneOrMoreOp { @ syntax = left; };
   265: 		};
   266: 
   267: 		/// This operation is composition of optional and one of more operators.
   268: 		/// Basically it is the composition of + and ? operators.
   269: 		op ZeroOrMoreOp(yf,100,*) {
   270: 			^ g:ZeroOrMoreOp { @ syntax = left; };
   271: 		};
   272: 
   273: 	};
   274: 	
   275: 	/// This context defines expressions that might happen in context 
   276: 	/// of modifiers expressions.
   277: 	context ModifiersSyntax {
   278: 		include BaseMappingSyntax;
   279: 
   280: 		/// This is modifier specification. It can contain optional wrapper.
   281: 		op composite ModifierOp(f) {
   282: 			^ g:ModifierOp {
   283: 				% modifier {
   284: 					@ value = token;
   285: 					@ wrapper = ref(WrapperDef)?; 
   286: 				};
   287: 			};
   288: 		};
   289: 	};
   290: 	
   291: 	// Free form composite syntax
   292: 	context CompositeSyntax {
   293: 		include CompositeOperatorsSyntax;
   294: 		import ModifiersSyntax = ModifiersSyntax;
   295: 		
   296: 
   297: 		/// Sequence statement is a simple block. Elements in this blocks are 
   298: 		/// matched sequentially. It is used to group syntax elements together.
   299: 		op composite Sequence(f) {
   300: 			ref(SequenceDef);
   301: 		};
   302: 		
   303: 		/// This is a section. The section matches token specified as its name
   304: 		/// and then an expression specified as its body. The section prefix is 
   305: 		/// intended to be unique in the context where section occurs. The section
   306: 		/// token is not reported as value to parser.
   307: 		op composite SectionOp(f) {
   308: 			^ g:SectionOp {
   309: 				% section {
   310: 					@ name = token;
   311: 					@ syntax = ref(SequenceDef);
   312: 				};
   313: 			};
   314: 		};
   315: 
   316: 		/// Reference to definition in this context or in included context.
   317: 		/// The expression is replaced with content of original definition.
   318: 		/// Recursion is not allowed to be created using references.
   319: 		op composite RefOp(f) {
   320: 			^ g:RefOp {
   321: 				% ref % ( {
   322: 					@ name = identifier;
   323: 				} % ) ;
   324: 			};
   325: 		};
   326: 
   327: 		/// Block reference. The statement matches block that that contains
   328: 		/// statements of the specified context. If no context is specified,
   329: 		/// reference to current context is assumed. Block produces a possibly
   330: 		/// empty sequence of objects. And it should happen in context of 
   331: 		/// of list property.
   332: 		op composite BlockRef(f) {
   333: 			^ g:BlockRef {
   334: 				% block { 
   335: 					% ( {
   336: 						@ context = identifier;
   337: 					} % ) ?; 
   338: 				};
   339: 			};
   340: 		};
   341: 		
   342: 		/// This is reusable fragment used to specify expression priority
   343: 		def ExpressionPriorityDef {
   344: 			% priority % = {
   345: 				@ priority = integer;
   346: 			};
   347: 		};
   348: 		/// Expression reference. This reference matches expression from 
   349: 		/// specified context and of specified priority. If context is omitted,
   350: 		/// current context is assumed. The expression production always 
   351: 		/// produces a single object as result if parsing is successful.
   352: 		op composite ExpressionRef(f) {
   353: 			^ g:ExpressionRef {
   354: 				 % expression {
   355: 					% ( {
   356: 						{
   357: 							ref(ExpressionPriorityDef);
   358: 						} | {	
   359: 							@ context = identifier;
   360: 							% , {
   361: 								ref(ExpressionPriorityDef);
   362: 							}?;
   363: 						};	
   364: 					} % ) ?;
   365: 				};
   366: 			};
   367: 		};
   368: 
   369: 
   370: 		/// This construct matches sequence separated by the specified 
   371: 		/// separator. This construct is just a useful shorthand. The separator 
   372: 		/// can be any specific token. The expression 
   373: 		///
   374: 		/// list , { 
   375: 		///   <content>;
   376: 		/// } 
   377: 		///
   378: 		/// is equivalent to 
   379: 		///
   380: 		/// {
   381: 		///    <content>; 
   382: 		///    section , {
   383: 		///       <content>; 
   384: 		///    }*;
   385: 		/// }
   386: 		op composite List(f) {
   387: 			^ g:ListOp {
   388: 				% list {
   389: 					@ separator = token;
   390: 					@ syntax = ref(SequenceDef);
   391: 				};
   392: 			};
   393: 		};
   394: 
   395: 		/// this construct matches brackets and syntax enclosed in brackets.
   396: 		/// This construct is just a useful shorthand. The separator 
   397: 		/// can be any specific token. For example, the expression 
   398: 		/// brackets ( ) { 
   399: 		///   <content>;
   400: 		/// } 
   401: 		///
   402: 		/// is equivalent to 
   403: 		///
   404: 		/// section ( {
   405: 		///    <content>;
   406: 		///    section ) {};
   407: 		/// };
   408: 		op composite BracketsOp(f) {
   409: 			^ g:BracketsOp {
   410: 				% brackets {
   411: 					@ open = token;
   412: 					@ close = token;
   413: 					@ syntax = ref(SequenceDef);
   414: 				};
   415: 			};
   416: 		};
   417: 		
   418: 		/// This construct matches set of modifiers. This construct
   419: 		/// matches any number or modifiers in any order. Each modifier
   420: 		/// if matches produces its text as a value. Wrapper specified 
   421: 		/// for modifiers construct applies to all modifiers inside it
   422: 		/// unless overridden by modifier.
   423: 		op composite ModifiersOp(f) {
   424: 			^ g:ModifiersOp {
   425: 				% modifiers {
   426: 					@ wrapper = ref(WrapperDef)?; 
   427: 					@ modifiers += block(ModifiersSyntax);
   428: 				};
   429: 			};
   430: 		};
   431: 		
   432: 		/// This construct matches any token or token specified in brackets.
   433: 		/// It produces a value of its text. If no token is specified, 
   434: 		/// the construct matches any significant token with exception of 
   435: 		/// documentation comment. See this grammar for numerous examples of its
   436: 		/// usage (including this definition).
   437: 		///
   438: 		/// Optional wrapper causes wrapping value produced by this expression
   439: 		/// into specified wrapper.
   440: 		op composite TokenOp(f) {
   441: 			^ g:TokenOp {
   442: 				% token {
   443: 					% ( {
   444: 						@ value = token;
   445: 					} % ) ?;
   446: 				};
   447: 				@ wrapper = ref(WrapperDef)?; 
   448: 			};
   449: 		};
   450: 		
   451: 		/// This operator matches string with specified quote kind.
   452: 		/// The quote must be specified. The operator produces matched text
   453: 		/// as a value.
   454: 		///
   455: 		/// Optional wrapper causes wrapping value produced by this expression
   456: 		/// into specified wrapper.
   457: 		op composite StringOp(f) {
   458: 			^ g:StringOp {
   459: 				% string % ( % quote % = {
   460: 				  @ quote = ref(String);
   461: 				} % );
   462: 				@ wrapper = ref(WrapperDef)?; 
   463: 			};
   464: 		};
   465: 		
   466: 		/// This operator matches any identifier. The operator produces matched text
   467: 		/// as a value.
   468: 		///
   469: 		/// Optional wrapper causes wrapping value produced by this expression
   470: 		/// into specified wrapper.
   471: 		op composite IdentifierOp(f) {
   472: 			^ g:IdentifierOp {
   473: 				% identifier {
   474: 				};
   475: 				@ wrapper = ref(WrapperDef)?; 
   476: 			};
   477: 		};
   478: 
   479: 
   480: 		/// This operator matches integer without suffix or with specified suffix
   481: 		/// The operator produces matched text as a value.
   482: 		///
   483: 		/// Optional wrapper causes wrapping value produced by this expression
   484: 		/// into specified wrapper.
   485: 		op composite IntegerOp(f) {
   486: 			^ g:IntegerOp {
   487: 				% integer {
   488: 					% ( {
   489: 						% suffix % = {
   490: 							@ suffix = ref(String);
   491: 						}?;
   492: 					} % ) ?;
   493: 					@ wrapper = ref(WrapperDef)?; 
   494: 				};
   495: 			};
   496: 		};
   497: 
   498: 
   499: 		/// This operator matches float without suffix or with specified suffix.
   500: 		/// The operator produces matched text as a value.
   501: 		///
   502: 		/// Optional wrapper causes wrapping value produced by this expression
   503: 		/// into specified wrapper.
   504: 		op composite FloatOp(f) {
   505: 			^ g:FloatOp {
   506: 				% float {
   507: 					% ( {
   508: 						% suffix % = {
   509: 							@ suffix = ref(String);
   510: 						}? ;
   511: 					} % ) ?;
   512: 				};
   513: 				@ wrapper = ref(WrapperDef)?; 
   514: 			};
   515: 		};
   516: 
   517: 
   518: 		/// This operator matches any graphics token.
   519: 		/// The operator produces matched text as a value.
   520: 		///
   521: 		/// Optional wrapper causes wrapping value produced by this expression
   522: 		/// into specified wrapper.
   523: 		op composite GraphicsOp(f) {
   524: 			^ g:GraphicsOp {
   525: 				% graphics;
   526: 				@ wrapper = ref(WrapperDef)?; 
   527: 			};
   528: 		};
   529: 
   530: 	};
   531: 	
   532: 	/// Composite operator syntax. 
   533: 	/// Note that this definition is oversimplified. There are additional 
   534: 	/// constraint that "left" and "right" expression might happen only on top 
   535: 	/// level. The construct will be possibly adjusted later. 
   536: 	context CompositeOpSyntax {
   537: 		include SimpleOpSyntax;
   538: 		include CompositeSyntax;
   539: 	};
   540: 	
   541: 	/// This context defines content of context statement. So it defines itself.
   542: 	context ContextContent {
   543: 		include Base;
   544: 		import compositeOpSyntax = CompositeOpSyntax;
   545: 		import simpleOpSyntax = SimpleOpSyntax;
   546: 		import compositeSyntax = CompositeSyntax;
   547: 		import documentationSyntax = DocumentationSyntax;
   548: 
   549: 		/// This is blank statement. It is used to attach attributes 
   550: 		/// and documentation comments.
   551: 		statement BlankStatement {
   552: 			^ g:BlankContextMember {
   553: 			};
   554: 		};
   555: 
   556: 		/// Operator associativity definition. It matches any valid associativity.
   557: 		def OpAssociativity {
   558: 			token(f) | token(xf) | token(yf) |token(xfy) |
   559: 			token(xfx) |token(yfx) |token(fx) |token(fy);
   560: 		};
   561: 
   562: 		/// Simple operator. See grammar comment for details.
   563: 		statement SimpleOp {
   564: 			^ g:SimpleOp {
   565: 				% simple {
   566: 					@ name = identifier;
   567: 					% ( {
   568: 						@ associativity = ref(OpAssociativity); 
   569: 						% , {
   570: 							@ priority = integer;
   571: 						} % , {
   572: 							@ text = token;
   573: 						};
   574: 					} % );
   575: 					@ syntax += block(simpleOpSyntax);
   576: 				};
   577: 			};
   578: 		};
   579: 
   580: 		/// Composite operator. See grammar comment for details.
   581: 		statement CompositeOp {
   582: 			^ g:CompositeOp {
   583: 				% composite {
   584: 					@ name = identifier;
   585: 					% ( {
   586: 						@ associativity = ref(OpAssociativity); 
   587: 						% , {
   588: 							@ priority = integer;
   589: 						}?;
   590: 					} % );
   591: 					@ syntax += block(compositeOpSyntax);
   592: 				};
   593: 			};
   594: 		};
   595: 
   596: 
   597: 		/// Attributes definition. Attributes can be applied only to
   598: 		/// statements. To apply them to expressions, define an composite
   599: 		/// operator that uses the same syntax. Such operator and attributes
   600: 		/// declaration can share syntax through def statement.
   601: 		statement Attributes {
   602: 			^ g:Attributes {
   603: 				% attributes {
   604: 					@ name = identifier;
   605: 					@ syntax += block(compositeSyntax);
   606: 				};
   607: 			};
   608: 		};
   609: 		
   610: 		/// Statement definition. Statement attempt to match entire segment.
   611: 		/// If statement matches part of segment and there are some 
   612: 		/// unmatched significant tokens left, it is a syntax error.
   613: 		statement Statement {
   614: 			^ g:Statement {
   615: 				% statement {
   616: 					@ name = identifier;
   617: 					@ syntax += block(compositeSyntax);
   618: 				};
   619: 			};
   620: 		};
   621: 
   622: 		/// Documentation syntax. It matches documentation comments before
   623: 		/// start of grammar. The definition is used to specify property
   624: 		/// where documentation is put.
   625: 		statement DocumentationSyntax {
   626: 			^ g:DocumentationSyntax {
   627: 				% documentation {
   628: 					@ name = identifier;
   629: 					@ syntax += block(documentationSyntax);
   630: 				};
   631: 			};
   632: 		};
   633: 
   634: 		/// A fragment definition. It is used to define reusable parts of the 
   635: 		/// syntax. References to definitions are replaced with content of the 
   636: 		/// definition, so it is an error for definition to refer to itself 
   637: 		/// through ref construct.
   638: 		statement Def {
   639: 			^ g:Def {
   640: 				% def {
   641: 					@ name = identifier;
   642: 					@ syntax += block(compositeSyntax);
   643: 				};
   644: 			};
   645: 		};
   646: 		
   647: 		/// Include operation cause all definitions except redefined 
   648: 		/// to be included in this context. It is an error if two definitions 
   649: 		/// are available using different paths. If wrapper chain is specified
   650: 		/// The statements will be wrapped into the specified chain.
   651: 		statement ContextInclude {
   652: 			^ g:ContextInclude {
   653: 				% include {
   654: 					@ contextName = identifier;
   655: 					@ wrappers += % wrapper {
   656: 						list / {
   657: 							ref(WrapperObject);
   658: 						};
   659: 					}?;
   660: 				};
   661: 			};
   662: 		};
   663: 
   664: 		/// Import operation makes context referenceable from this context or 
   665: 		/// allows redefinition of context reference.
   666: 		statement ContextImport {
   667: 			^ g:ContextImport {
   668: 				% import {
   669: 					@ localName = identifier;
   670: 					% = {
   671: 						@ contextName = identifier;
   672: 						% from {
   673: 							@ grammarName = identifier;
   674: 						}?;
   675: 					};
   676: 				};
   677: 			};
   678: 		};
   679: 	};
   680: 	
   681: 	/// This context defines grammar content.
   682: 	context GrammarContent {
   683: 		include Base;
   684: 		import contextContent = ContextContent;
   685: 		
   686: 		/// This definition provides way of referencing other grammars.
   687: 		def GrammarRef {
   688: 			{
   689: 				@ systemId = ref(String);
   690: 				% public {
   691: 					@ publicId = ref(String);
   692: 				}?;
   693: 			} | {
   694: 				% public {
   695: 					@ publicId = ref(String);
   696: 				};
   697: 			};				
   698: 		};
   699: 
   700: 		/// This is blank statement. It is used to attach attributes 
   701: 		/// and documentation comments.
   702: 		statement BlankStatement {
   703: 			^ g:BlankGrammarMember {
   704: 			};
   705: 		};
   706: 
   707: 		
   708: 		/// This is an include statement. Include causes all context from 
   709: 		/// included grammar to be added to current grammar. The definitions
   710: 		/// from grammar include are added only if current grammar does not 
   711: 		/// have definitions with the same name.
   712: 		///
   713: 		/// Grammar imports and context imports also follow this inclusion rule.
   714: 		/// It is an error to include two different non-shadowed definitions by
   715: 		/// different include paths.
   716: 		statement Include {
   717: 			^ g:GrammarInclude {
   718: 				% include {
   719: 					ref(GrammarRef);
   720: 				};
   721: 			};
   722: 		};
   723: 
   724: 		/// This is grammar import statement. A statement allows contexts of this
   725: 		/// grammar  to import context from specified grammar.
   726: 		statement Import {
   727: 			^ g:GrammarImport {
   728: 				% import {
   729: 					@ name = identifier;
   730: 				} % = {
   731: 					ref(GrammarRef);
   732: 				};	
   733: 			};
   734: 		};
   735: 
   736: 
   737: 		/// Namespace declaration is used to declare namespace prefix. The 
   738: 		/// prefix declaration is local to grammar.
   739: 		statement Namespace {
   740: 			^ g:Namespace {
   741: 				% namespace {
   742: 					@ prefix = identifier;
   743: 					% = {
   744: 						@ uri = ref(String);
   745: 					};	
   746: 				};
   747: 			};
   748: 		};
   749: 
   750: 		/// Context definition. This definition is used to define context.
   751: 		/// Context may be default and abstract. Abstract contexts 
   752: 		/// cannot be used for parsing and are used only in context include.
   753: 		/// Abstract contexts may be imported only by abstract contexts.
   754: 		///
   755: 		/// Default context is a context that used to parse source when
   756: 		/// no context is specified in doctype. 
   757: 		statement Context {
   758: 			^ g:Context {
   759: 				% context {
   760: 					modifiers wrapper g:Modifier.value {
   761: 						@ abstractModifier = modifier abstract;
   762: 						@ defaultModifier = modifier default;
   763: 					};
   764: 					@ name = identifier;
   765: 					@ content += block(contextContent);
   766: 				};
   767: 			};
   768: 		};
   769: 	};
   770: 	
   771: 	/// This context contains definition of grammar construct itself
   772: 	context default GrammarSource {
   773: 		include Base;
   774: 		import grammarContent = GrammarContent;
   775: 
   776: 		/// This is blank statement. It is used to attach attributes 
   777: 		/// and documentation comments. It is ignored during grammar
   778: 		/// compilation.
   779: 		statement BlankStatement {
   780: 			^ g:BlankTopLevel {
   781: 			};
   782: 		};
   783: 
   784: 		/// Grammar statement. It defines grammar. Grammar name is purely 
   785: 		/// informative and is used in reported events to identify grammar
   786: 		/// by logical name rather by URI that happens to be current grammar
   787: 		/// location.
   788: 		///
   789: 		/// Grammar can be abstract, in that case it cannot be instantiated
   790: 		/// and referenced from doctype. It can be only included into other 
   791: 		/// grammars.
   792: 		statement Grammar {
   793: 			^ g:Grammar {
   794: 				% grammar {
   795: 					modifiers wrapper g:Modifier.value {
   796: 						@ abstractModifier = modifier abstract;
   797: 					};
   798: 					@ name += list . {identifier;};
   799: 					@ content += block(grammarContent);
   800: 				};
   801: 			};
   802: 		};
   803: 	};
   804: };