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