1:
2: doctype public "-//IDN etl.sf.net//ETL//Grammar 0.2.1";
3: /// This is a grammar for EJ language. The language is targeted to cover
4: /// all features of Java language in the way that is similar to one used
5: /// in Java.
6: ///
7: /// Note that the goal of this sample was to get a sample that is as close
8: /// to Java as possible within ETL. However if the task is to get a good language
9: /// for JVM, a better languages are possible. For example taking more functional
10: /// approach is possible allowing constructs like:
11: /// "let a := {let b:= Math.sin(Math.PI/3); 2*b*(b+1);};"
12: ///
13: /// So do not use this source as a sample of the language design. It has
14: /// known quality issues in this area.
15: grammar net.sf.etl.samples.ej.EJ {
16: include "CommonControlFlow.g.etl";
17: include "CommonOperators.g.etl";
18: namespace ej = "http://etl.sf.net/2006/samples/ej/0.1";
19: /// This context contains common definitions that are shared
20: /// between statements and expressions.
21: context abstract Base {
22: import Expressions = Expressions;
23: import TypeExpressions = TypeExpressions;
24: import ClassContents = ClassContents;
25: import MethodContent = MethodContent;
26: import NameExpressions = NameExpressions;
27: def NameFragment {
28: ^ ej:Identifier {
29: {
30: @ value = identifier;
31: } | {
32: @ quotedValue = string(prefix=q|Q,quote = "'");
33: };
34: };
35: };
36: def AttributesDef {
37: @ attributeSets += {
38: ^ ej:AttributeSet {
39: % @ {
40: % [{
41: @ attributes += list, {
42: expression(Expressions, precedence = 100);
43: };
44: } % ];
45: };
46: };
47: };
48: };
49: def TemplateBounds {
50: {
51: {
52: % super {
53: @ superToTypes += list & {
54: expression(TypeExpressions);
55: };
56: };
57: } | {
58: % extends {
59: @ extendedTypes += list & {
60: expression(TypeExpressions);
61: };
62: };
63: };
64: } ?;
65: };
66: def ClassBlockDef {
67: ^ ej:ClassBlock {
68: @ content += block(ClassContents);
69: };
70: };
71: def TemplateParameters {
72: % [ {
73: @ templateParameters += list, {
74: ^ ej:TemplateParameter {
75: @ name = expression(NameExpressions);
76: ref(TemplateBounds);
77: };
78: };
79: } % ];
80: };
81: def NameDefinitionFragment {
82: @ classifier = expression(TypeExpressions);
83: @ name = expression(NameExpressions);
84: };
85: def ParameterFragment {
86: ^ ej:Parameter {
87: ref(AttributesDef) ?;
88: modifiers wrapper ej:Modifier.value {
89: @ finalModifier = modifier final;
90: };
91: ref(NameDefinitionFragment);
92: };
93: };
94: def VariableSetFragment {
95: @ classifier = expression(TypeExpressions);
96: @ variables += list, {
97: ^ ej:Variable {
98: @ name = expression(NameExpressions);
99: % = {
100: @ initialValue = expression(Expressions);
101: } ?;
102: };
103: };
104: };
105: def MethodBlockFragment {
106: ^ ej:MethodBlock {
107: @ content += block(MethodContent);
108: };
109: };
110: };
111: /// This context contains common definitions used in statements across
112: /// all contexts.
113: context abstract BaseStatements {
114: include Base;
115: attributes Attributes {
116: ref(AttributesDef);
117: };
118: documentation Documentation {
119: @ documentation += doclines wrapper ej:DocumentationLine.text;
120: };
121: };
122: context NameExpressions {
123: include Base;
124: op composite Identifier(f) {
125: ref(NameFragment);
126: };
127: };
128: context PackageNameExpressions {
129: include NameExpressions;
130: op AccessOp(yfx, 100,.) {
131: ^ ej:AccessOp {
132: @ accessed = left;
133: @ feature = right;
134: };
135: };
136: };
137: context TypeExpressions {
138: include PackageNameExpressions;
139: op composite ApplySquareOp(yf, 100) {
140: ^ ej:ApplySquareOp {
141: @ functor = left;
142: @ args += %[{
143: list, {
144: expression;
145: };
146: } % ];
147: };
148: };
149: op composite ArrayType(f) {
150: ^ ej:PrimitiveType {
151: @ name = token(array);
152: };
153: };
154: op composite BooleanType(f) {
155: ^ ej:PrimitiveType {
156: @ name = token(boolean);
157: };
158: };
159: op composite ByteType(f) {
160: ^ ej:PrimitiveType {
161: @ name = token(byte);
162: };
163: };
164: op composite ShortType(f) {
165: ^ ej:PrimitiveType {
166: @ name = token(short);
167: };
168: };
169: op composite IntType(f) {
170: ^ ej:PrimitiveType {
171: @ name = token(int);
172: };
173: };
174: op composite LongType(f) {
175: ^ ej:PrimitiveType {
176: @ name = token(long);
177: };
178: };
179: op composite CharType(f) {
180: ^ ej:PrimitiveType {
181: @ name = token(char);
182: };
183: };
184: op composite FloatType(f) {
185: ^ ej:PrimitiveType {
186: @ name = token(float);
187: };
188: };
189: op composite DoubleType(f) {
190: ^ ej:PrimitiveType {
191: @ name = token(double);
192: };
193: };
194: op composite VoidType(f) {
195: ^ ej:PrimitiveType {
196: @ name = token(void);
197: };
198: };
199: op composite WildcardType(f) {
200: ^ ej:WildcardType {
201: % ? {
202: ref(TemplateBounds);
203: };
204: };
205: };
206: };
207: context Expressions {
208: include TypeExpressions;
209: include CommonOperators;
210: import ClassContents = ClassContents;
211: import TypeExpressions = TypeExpressions;
212: op composite ThisReference(f) {
213: ^ ej:ThisReference {
214: @ name = token(this);
215: };
216: };
217: op composite SuperReference(f) {
218: ^ ej:SuperReference {
219: @ name = token(super);
220: };
221: };
222: op composite NullReference(f) {
223: ^ ej:NullReference {
224: @ value = token(null);
225: };
226: };
227: op composite BooleanLiteral(f) {
228: ^ ej:BooleanLiteral {
229: @ value = token(true) | token(false);
230: };
231: };
232: op composite StringLiteral(f) {
233: ^ ej:StringLiteral {
234: @ value = string(quote = "\"");
235: };
236: };
237: /// Note that constraint that literal can contain only one
238: /// character is not not enforced at grammar level.
239: op composite CharacterLiteral(f) {
240: ^ ej:CharacterLiteral {
241: @ value = string(quote = "'");
242: };
243: };
244: op composite IntegerLiteral(f) {
245: ^ ej:IntegerLiteral {
246: @ value = integer;
247: };
248: };
249: op composite LongIntegerLiteral(f) {
250: ^ ej:LongIntegerLiteral {
251: @ value = integer(suffix = l|L);
252: };
253: };
254: op composite DoubleLiteral(f) {
255: ^ ej:DoubleLiteral {
256: @ value = integer(suffix = d|D) | float | float(suffix = d|D);
257: };
258: };
259: op composite FloatLiteral(f) {
260: ^ ej:FloatLiteral {
261: @ value = integer(suffix = f|F) | float(suffix = f|F);
262: };
263: };
264: def ArrayConstructorFragment {
265: ^ ej:ArrayConstructor {
266: %[{
267: @ values += list, {
268: expression;
269: } ?;
270: } % ];
271: };
272: };
273: op composite ArrayConstructor(f) {
274: ref(ArrayConstructorFragment);
275: };
276: op composite NewOp(f) {
277: ^ ej:NewOp {
278: % new {
279: @ classifier = expression(TypeExpressions, precedence = 100);
280: {
281: @ arrayConstructor = % with {
282: ref(ArrayConstructorFragment);
283: };
284: } | {
285: @ args += %({
286: list, {
287: expression;
288: } ?;
289: } %);
290: @ classBody = ref(ClassBlockDef) ?;
291: };
292: };
293: };
294: };
295: op composite IdentityOp(f) {
296: ^ ej:IdentityOp {
297: %({
298: @ value = expression;
299: } %);
300: };
301: };
302: op composite ApplyRound(yf, 100) {
303: ^ ej:ApplyRoundOp {
304: @ functor = left;
305: @ args += %({
306: list, {
307: expression;
308: } ?;
309: } %);
310: };
311: };
312: /// Note it is possible to enforce more constraints by
313: /// using composite operator.
314: op CastOp(xfx, 300, as) {
315: ^ ej:CastOp {
316: @ value = left;
317: @ classifier = right;
318: };
319: };
320: op InstanceOfOp(xfx, 700, instanceof) {
321: ^ ej:InstanceOfOp {
322: @ value = left;
323: @ classifier = right;
324: };
325: };
326: op AssignmentOp(xfy, 1500, =) {
327: ^ ej:AssignmentOp {
328: @ leftHandSide = left;
329: @ value = right;
330: };
331: };
332: op PlusAssignmentOp(xfy, 1500, +=) {
333: ^ ej:PlusAssignmentOp {
334: @ leftHandSide = left;
335: @ value = right;
336: };
337: };
338: op MinusAssignmentOp(xfy, 1500, -=) {
339: ^ ej:MinusAssignmentOp {
340: @ leftHandSide = left;
341: @ value = right;
342: };
343: };
344: op MultiplyAssignmentOp(xfy, 1500, *=) {
345: ^ ej:MultiplyAssignmentOp {
346: @ leftHandSide = left;
347: @ value = right;
348: };
349: };
350: op DivideAssignmentOp(xfy, 1500, /=) {
351: ^ ej:DivideAssignmentOp {
352: @ leftHandSide = left;
353: @ value = right;
354: };
355: };
356: op BitwiseAndAssignmentOp(xfy, 1500, &=) {
357: ^ ej:BitwiseAndAssignmentOp {
358: @ leftHandSide = left;
359: @ value = right;
360: };
361: };
362: op BitwiseOrAssignmentOp(xfy, 1500, |=) {
363: ^ ej:BitwiseOrAssignmentOp {
364: @ leftHandSide = left;
365: @ value = right;
366: };
367: };
368: op BitwiseXorAssignmentOp(xfy, 1500, ^=) {
369: ^ ej:BitwiseXorAssignmentOp {
370: @ leftHandSide = left;
371: @ value = right;
372: };
373: };
374: op RemainderAssignmentOp(xfy, 1500, %=) {
375: ^ ej:RemainderAssignmentOp {
376: @ leftHandSide = left;
377: @ value = right;
378: };
379: };
380: op LeftShiftAssignmentOp(xfy, 1500, <<=) {
381: ^ ej:LeftShiftAssignmentOp {
382: @ leftHandSide = left;
383: @ value = right;
384: };
385: };
386: op RightShiftAssignmentOp(xfy, 1500, >>=) {
387: ^ ej:RightShiftAssignmentOp {
388: @ leftHandSide = left;
389: @ value = right;
390: };
391: };
392: op ZeroExtensionRightShiftAssignmentOp(xfy, 1500, >>>=) {
393: ^ ej:ZeroExtensionRightShiftAssignmentOp {
394: @ leftHandSide = left;
395: @ value = right;
396: };
397: };
398: op PrefixIncrementOp(fy, 200, ++) {
399: ^ ej:PrefixIncrementOp {
400: @ value = right;
401: };
402: };
403: op PostfixIncrementOp(yf, 300, ++) {
404: ^ ej:PostfixIncrementOp {
405: @ value = left;
406: };
407: };
408: op PrefixDecrementOp(fy, 200, --) {
409: ^ ej:PrefixDecrementOp {
410: @ value = right;
411: };
412: };
413: op PostfixDecrementOp(yf, 300, --) {
414: ^ ej:PostfixDecrementOp {
415: @ value = left;
416: };
417: };
418: };
419: context abstract MethodContentCommons {
420: include BaseStatements;
421: include CommonControlFlow_Commons;
422: /// Redefine generic expression from common control flow
423: def CommonControlFlow_GenericExpression {
424: expression(Expressions);
425: };
426: };
427: context MethodContent {
428: include InnerClassifiers wrapper ej:MethodClassifier.classifier;
429: include MethodContentCommons;
430: include CommonControlFlow;
431: import CommonControlFlow_SwitchContent = MethodContent_SwitchContent;
432: /// Redefine fragment to refer to itself
433: def MethodBlockFragment {
434: ^ ej:MethodBlock {
435: @ content += block;
436: };
437: };
438: /// Redefine exception pattern from common control flow
439: def CommonControlFlow_ParameterPattern {
440: ref(ParameterFragment);
441: };
442: /// This a blank statement
443: statement EmptyStatement {
444: ^ ej:EmptyStatement {
445: };
446: };
447: statement ForStatement {
448: ^ ej:ForStatement {
449: % for {
450: ref(CommonControlFlow_LabelFragment) ?;
451: %({
452: {
453: @ initVariableDeclaration = ^ ej:LocalVarStatement {
454: ref(LocalVariablesStatementFragment);
455: };
456: } | {
457: @ initExpressions += expression(Expressions);
458: } | {
459: };
460: % :{
461: @ condition = expression(Expressions) ?;
462: };
463: % :{
464: @ updateExpressions += list, {
465: expression(Expressions);
466: } ?;
467: };
468: } %);
469: ref(CommonControlFlow_Body);
470: };
471: };
472: };
473: statement LocalVarStatement {
474: ^ ej:LocalVarStatement {
475: ref(LocalVariablesStatementFragment);
476: };
477: };
478: def LocalVariablesStatementFragment {
479: % var {
480: modifiers wrapper ej:Modifier.value {
481: @ finalModifier = modifier final;
482: };
483: ref(VariableSetFragment);
484: };
485: };
486: statement SynchronizedStatement {
487: ^ ej:SynchronizedStatement {
488: % synchronized {
489: %({
490: @ value = expression(Expressions);
491: } %);
492: ref(CommonControlFlow_Body);
493: };
494: };
495: };
496: statement AssertStatement {
497: ^ ej:AssertStatement {
498: % assert {
499: @ test = expression(Expressions);
500: };
501: % :{
502: @ message = expression(Expressions);
503: } ?;
504: };
505: };
506: };
507: context MethodContent_SwitchContent {
508: include MethodContentCommons;
509: include CommonControlFlow_SwitchContent;
510: import CommonControlFlow = MethodContent;
511: };
512: context abstract ClassifierContent {
513: include BaseStatements;
514: import NameExpressions = NameExpressions;
515: include InnerClassifiers wrapper ej:InnerClassifier.classifier;
516: def MethodSignatureFragment {
517: @ returnType = expression(TypeExpressions);
518: ref(ConstructorSignatureFragment);
519: };
520: def ConstructorSignatureFragment {
521: @ name = ref(NameFragment);
522: %({
523: list, {
524: @ parameters += ref(ParameterFragment);
525: } ?;
526: } %);
527: % throws {
528: list, {
529: @ exceptions += expression(TypeExpressions);
530: };
531: } ?;
532: };
533: };
534: context ClassContents {
535: include ClassifierContent;
536: statement MethodStatement {
537: ^ ej:MethodStatement {
538: % to {
539: ref(TemplateParameters) ?;
540: modifiers wrapper ej:Modifier.value {
541: @ visibilityModifier = modifier public;
542: @ visibilityModifier = modifier protected;
543: @ visibilityModifier = modifier private;
544: @ staticModifier = modifier static;
545: @ strictfpModifier = modifier strictfp;
546: @ abstractModifier = modifier abstract;
547: @ finalModifier = modifier final;
548: @ synchronizedModifier = modifier synchronized;
549: };
550: ref(MethodSignatureFragment);
551: };
552: @ body = ref(MethodBlockFragment) ?;
553: };
554: };
555: statement FieldStatement {
556: ^ ej:FieldStatement {
557: % var {
558: modifiers wrapper ej:Modifier.value {
559: @ visibilityModifier = modifier public;
560: @ visibilityModifier = modifier protected;
561: @ visibilityModifier = modifier private;
562: @ staticModifier = modifier static;
563: @ abstractModifier = modifier abstract;
564: @ finalModifier = modifier final;
565: @ transientModifier = modifier transient;
566: @ volatileModifier = modifier volatile;
567: };
568: ref(VariableSetFragment);
569: };
570: };
571: };
572: statement InitStatement {
573: ^ ej:InitStatement {
574: @ body = ref(MethodBlockFragment);
575: };
576: };
577: statement StaticInitStatement {
578: ^ ej:StaticInitStatement {
579: % static {
580: @ body = ref(MethodBlockFragment);
581: };
582: };
583: };
584: statement ConstructorStatement {
585: ^ ej:ConstructorStatement {
586: % maker {
587: modifiers wrapper ej:Modifier.value {
588: @ visibilityModifier = modifier public;
589: @ visibilityModifier = modifier protected;
590: @ visibilityModifier = modifier private;
591: };
592: ref(ConstructorSignatureFragment);
593: };
594: @ body = ref(MethodBlockFragment);
595: };
596: };
597: };
598: context InterfaceContents {
599: include ClassifierContent;
600: statement MethodStatement {
601: ^ ej:MethodStatement {
602: % to {
603: modifiers wrapper ej:Modifier.value {
604: @ visibilityModifier = modifier public;
605: @ abstractModifier = modifier abstract;
606: };
607: ref(MethodSignatureFragment);
608: };
609: };
610: };
611: statement FieldStatement {
612: ^ ej:FieldStatement {
613: % var {
614: modifiers wrapper ej:Modifier.value {
615: @ visibilityModifier = modifier public;
616: @ staticModifier = modifier static;
617: @ finalModifier = modifier final;
618: };
619: ref(VariableSetFragment);
620: };
621: };
622: };
623: };
624: context AttributeContents {
625: include BaseStatements;
626: statement FieldStatement {
627: ^ ej:FieldStatement {
628: % var {
629: ref(VariableSetFragment);
630: };
631: };
632: };
633: };
634: context EnumerationContents {
635: include ClassContents;
636: statement LiteralStatement {
637: ^ ej:EnumLiteral {
638: % literal {
639: @ name = expression(NameExpressions);
640: %({
641: @ args += list, {
642: expression(Expressions);
643: };
644: } %) ?;
645: {
646: @ body = ref(ClassBlockDef);
647: } ?;
648: };
649: };
650: };
651: };
652: context abstract InnerClassifiers {
653: include BaseStatements;
654: import EnumerationContents = EnumerationContents;
655: import ClassContents = ClassContents;
656: import InterfaceContents = InterfaceContents;
657: def ClassModifiersDef {
658: modifiers wrapper ej:Modifier.value {
659: @ visibilityModifier = modifier public;
660: @ visibilityModifier = modifier protected;
661: @ visibilityModifier = modifier private;
662: @ staticModifier = modifier static;
663: @ strictfpModifier = modifier strictfp;
664: @ abstractModifier = modifier abstract;
665: @ finalModifier = modifier final;
666: @ synchronizedModifier = modifier syncrhonized;
667: };
668: };
669: statement ClassStatement {
670: ^ ej:ClassStatement {
671: % class {
672: ref(ClassModifiersDef);
673: @ name = ref(NameFragment);
674: ref(TemplateParameters) ?;
675: };
676: % extends {
677: @ extendedType = expression(TypeExpressions);
678: } ?;
679: % implements {
680: @ implementedTypes += list, {
681: expression(TypeExpressions);
682: };
683: } ?;
684: @ contents += block(ClassContents);
685: };
686: };
687: statement InterfaceStatement {
688: ^ ej:InterfaceStatement {
689: % interface {
690: modifiers wrapper ej:Modifier.value {
691: @ visibilityModifier = modifier public;
692: };
693: @ name = ref(NameFragment);
694: ref(TemplateParameters) ?;
695: };
696: % extends {
697: @ extendedTypes += list, {
698: expression(TypeExpressions);
699: };
700: } ?;
701: @ contents += block(InterfaceContents);
702: };
703: };
704: statement EnumStatement {
705: ^ ej:EnumStatement {
706: % enum {
707: ref(ClassModifiersDef);
708: @ name = ref(NameFragment);
709: };
710: @ contents += block(EnumerationContents);
711: };
712: };
713: };
714: context AllClassifiers {
715: include InnerClassifiers;
716: import AttributeContents = AttributeContents;
717: statement AttributeDefinition {
718: ^ ej:AttributeDefinition {
719: % attribute {
720: modifiers wrapper ej:Modifier.value {
721: @ visibilityModifier = modifier public;
722: };
723: @ name = ref(NameFragment);
724: };
725: @ contents += block(AttributeContents);
726: };
727: };
728: };
729: context default TopLevel {
730: include AllClassifiers wrapper ej:TopLevelClassifier.classifier;
731: import PackageNameExpressions = PackageNameExpressions;
732: /// This is an package statement.
733: /// <usage>
734: /// package java.awt;
735: /// </usage>
736: statement PackageStatement {
737: ^ ej:PackageStatement {
738: % package {
739: @ name = expression(PackageNameExpressions);
740: };
741: };
742: };
743: /// This is an import statement.
744: /// <usage>
745: /// import java.util.List;
746: /// import all static java.lang.Math;
747: /// import all java.rmi;
748: /// </usage>
749: statement ImportStatement {
750: ^ ej:ImportStatement {
751: % import {
752: modifiers wrapper ej:Modifier.value {
753: @ allModifier = modifier all;
754: @ staticModifier = modifier static;
755: };
756: @ importedPackage = expression(PackageNameExpressions);
757: };
758: };
759: };
760: };
761: };