1: doctype public "-//IDN etl.sf.net//ETL//Grammar 0.2.1";
2: /// This is a grammar for ecore language. This language
3: /// is used to create Ecore models in the textual notation.
4: /// This quite simplified grammar. It basically supports
5: /// Library sample and little more. Object references
6: /// and contained objects in annotations are not supported here.
7: ///
8: grammar net.sf.etl.samples.ecore.Ecore {
9: namespace default e = "http://etl.sf.net/2006/samples/ecore/0.1";
10: /// This is a base context that contains common definitions
11: /// that are used by other contexts.
12: context abstract Base {
13: def IdentifierDef {
14: ^ e:Identifier {
15: {
16: @ name = identifier;
17: } | {
18: @ quotedName = string(prefix=q|Q, quote = "'");
19: };
20: };
21: };
22: };
23: /// This is a base context for statements that contains common
24: /// definitions for statements and declaration of attributes
25: /// and docs.
26: context abstract BaseStatements {
27: include Base;
28: attributes Annotation {
29: @ annotations = % @ % [ {
30: list, {
31: ^ e:Annotation {
32: @ source = identifier | string(quote = "\"");
33: @ details += %( {
34: list, {
35: ^ e:AnnotationDetail {
36: @ key = identifier | string(quote = "\"");
37: % = ;
38: @ value = string(quote = "\"");
39: };
40: } ?;
41: } %);
42: };
43: };
44: } % ] +;
45:
46: };
47: documentation Documentation {
48: @ documentation += doclines wrapper e:DocumentationLine.text;
49: };
50: };
51: context QualifiedNames {
52: include Base;
53: /// Identifier operator
54: op composite Identifier(f) {
55: ref(IdentifierDef);
56: };
57: op NamespaceAccessOp(yfx, 100, ::) {
58: @ namespace = left;
59: @ object = right;
60: };
61: };
62: context TypeExpressions {
63: include QualifiedNames;
64: op composite BooleanType(f) {
65: ^ e:PrimitiveType {
66: @ name = token(boolean);
67: };
68: };
69: op composite ByteType(f) {
70: ^ e:PrimitiveType {
71: @ name = token(byte);
72: };
73: };
74: op composite ShortType(f) {
75: ^ e:PrimitiveType {
76: @ name = token(short);
77: };
78: };
79: op composite IntType(f) {
80: ^ e:PrimitiveType {
81: @ name = token(int);
82: };
83: };
84: op composite LongType(f) {
85: ^ e:PrimitiveType {
86: @ name = token(long);
87: };
88: };
89: op composite CharType(f) {
90: ^ e:PrimitiveType {
91: @ name = token(char);
92: };
93: };
94: op composite FloatType(f) {
95: ^ e:PrimitiveType {
96: @ name = token(float);
97: };
98: };
99: op composite DoubleType(f) {
100: ^ e:PrimitiveType {
101: @ name = token(double);
102: };
103: };
104: op composite StringType(f) {
105: ^ e:PrimitiveType {
106: @ name = token(String);
107: };
108: };
109: };
110: /// Only value literals are allowed for values
111: context ValueExpressions {
112: op composite BooleanLiteral(f) {
113: @ value = token(true) | token(false);
114: };
115: op composite StringLiteral(f) {
116: @ value = string(quote = "\"");
117: };
118: /// Note that constraint that literal can contain only one
119: /// character is not not enforced at grammar level.
120: op composite CharacterLiteral(f) {
121: @ value = string(quote = "'");
122: };
123: op composite IntegerLiteral(f) {
124: @ value = integer;
125: };
126: op composite LongIntegerLiteral(f) {
127: @ value = integer(suffix = l|L);
128: };
129: op composite DoubleLiteral(f) {
130: @ value = integer(suffix = d|D) | float | float(suffix = d|D);
131: };
132: op composite FloatLiteral(f) {
133: @ value = integer(suffix = f|F) | float(suffix = f|F);
134: };
135: };
136: context EnumerationContents {
137: include BaseStatements;
138: statement EnumLiteral {
139: % literal;
140: @ name = ref(IdentifierDef);
141: };
142: };
143: context ClassContents {
144: include BaseStatements;
145: import TypeExpressions = TypeExpressions;
146: import ValueExpressions = ValueExpressions;
147: /// This is a simple name definition. It is used in parameters and variables
148: def NameDefinition {
149: @ name = ref(IdentifierDef);
150: ref(TypeSection);
151: };
152: /// This is a type section
153: def TypeSection {
154: % :{
155: @ type = expression(TypeExpressions);
156: % [ {
157: ref(MultiplicityDef);
158: } % ] ?;
159: };
160: };
161: /// Note that multiplicity is accepted in the following forms
162: /// 1, 0..1, 1..*, *. If upper bound is not defined, it is assumed
163: /// to be equal to lower bound. If lower bound is not definied,
164: /// (the case of *), it is assumed to be 0.
165: def MultiplicityDef {
166: {
167: @ lowBound = integer;
168: % .. {
169: @ uppperBound = integer | token(*);
170: } ?;
171: } | {
172: @ upperBound = token(*);
173: };
174: };
175: /// This is variable statement.
176: statement Var {
177: % var;
178: modifiers {
179: @ composite = modifier composite;
180: @ unsettable = modifier unsettable;
181: @ readonly = modifier readonly;
182: @ volatile = modifier volatile;
183: @ derived = modifier derived;
184: @ transient = modifier transient;
185: };
186: ref(NameDefinition);
187: % = {
188: @ initialValue = expression(ValueExpressions);
189: } | % inverseof {
190: @ inverseRole = identifier;
191: } | {
192: };
193: };
194: /// This is a method statement
195: statement Operation {
196: % to ;
197: @ name = ref(IdentifierDef);
198: %(;
199: list, {
200: ^ e:Parameter {
201: ref(NameDefinition);
202: };
203: } ?;
204: % );
205: ref(TypeSection) ?;
206: % throws {
207: @ exceptions = list, {
208: expression(TypeExpressions);
209: };
210: } ?;
211: };
212: };
213: context DataTypeContents {
214: include BaseStatements;
215: /// datatype context should have at least one statement in order
216: /// for blocks to be allowed
217: statement BlankDatatypeStatement {
218: };
219: };
220: /// This context defines package construct
221: context abstract PackageDefinitionContext {
222: include BaseStatements;
223: def PackageContentsBlockDef {
224: block(PackageContents);
225: };
226: statement Package {
227: % package ;
228: @ name = ref(IdentifierDef);
229: @ contents += ref(PackageContentsBlockDef);
230: };
231: };
232: /// This context defines package contents construct
233: context PackageContents {
234: include PackageDefinitionContext;
235: def PackageContentsBlockDef {
236: block;
237: };
238: statement Namespace {
239: % namespace;
240: @ nsPrefix = identifier;
241: % = ;
242: @ nsUri = string(quote = "\"");
243: };
244: statement ImportStatement {
245: % import;
246: @ uri = string(quote = "\"");
247: % as ;
248: @ name = ref(IdentifierDef);
249: };
250: statement With {
251: % with;
252: @ name = expression(QualifiedNames);
253: };
254: statement DataType {
255: % datatype;
256: modifiers {
257: @ serializable = modifier serializable;
258: };
259: @ name = ref(IdentifierDef);
260: @ contents += block(DataTypeContents);
261: };
262: statement Enum {
263: % enumeration;
264: @ name = ref(IdentifierDef);
265: @ contents = block(EnumerationContents);
266: };
267: statement Class {
268: % class;
269: modifiers {
270: @ abstract = modifier abstract;
271: @ interface = modifier interface;
272: };
273: @ name = ref(IdentifierDef);
274: % extends {
275: @ supertTypes = list, {
276: expression(QualifiedNames);
277: };
278: } ?;
279: @ contents = block(ClassContents);
280: };
281: };
282: context default TopLevel {
283: include PackageDefinitionContext;
284: statement AnnotationSource {
285: % annotation_source;
286: @ localName = identifier;
287: % = ;
288: @ uri = string(quote = "\"");
289: };
290: };
291: };