1:
2: doctype public "-//IDN etl.sf.net//ETL//Grammar 0.2.1";
3: /// This abstract grammar defines common control flow constructs
4: /// for imperative programming languages. Functional programming
5: /// languages would likely need completely different set of constructs.
6: /// Note that grammar does not dictate style of definitions in the
7: /// language.
8: ///
9: /// The constructs are mostly rip off Java and C# languages. However
10: /// they are somewhat tweaked to conform more to ETL style. There is no
11: /// "goto" statement in grammar. It might be added in separate grammar.
12: /// However grammar contains common loop continue/break variation of goto and
13: /// it also contains "continue case" for implementing fall through in switch.
14: ///
15: /// This grammar demonstrates how to create a reusable module that can be used in
16: /// other grammars.
17: grammar abstract net.sf.etl.samples.ej.CommonControlFlow {
18: namespace c = "http://etl.sf.net/2006/samples/ej/0.1";
19:
20:
21: context abstract CommonControlFlow_Commons {
22: /// This is an extension point that should be overridden by
23: /// contexts that include this context. It should reference
24: /// a generic expression. The definition must be redefined
25: /// in including grammars.
26: ///
27: /// The definition should refer to top level expression
28: def CommonControlFlow_GenericExpression {
29: };
30: };
31: /// This context contains common control flow constructs for
32: /// imperative programming languages. Note that context is abstract
33: /// and it cannot be used directly. The context has to be specialized
34: /// in order to be useful.
35: context abstract CommonControlFlow {
36: include CommonControlFlow_Commons;
37: import CommonControlFlow_SwitchContent = CommonControlFlow_SwitchContent;
38:
39:
40:
41:
42: /// Common label fragment
43: def CommonControlFlow_LabelFragment {
44: @ label = identifier wrapper c:Label.name;
45: };
46: /// This extension point may be overridden by context that define
47: /// conditional expression in different way than generic expression.
48: /// For example, it is possible to specify that condition should of
49: /// level that has lower precedence than assignment level.
50: def CommonControlFlow_ConditionalExpression {
51: ref(CommonControlFlow_GenericExpression);
52: };
53: /// This extension point may be overridden by context that define
54: /// conditional expression in different way than generic expression.
55: /// For example, it is possible to specify that condition should of
56: /// level that has lower precedence than assignment level.
57: def CommonControlFlow_ConditionFragment {
58: %({
59: @ condition = ref(CommonControlFlow_ConditionalExpression);
60: } %);
61: };
62: /// This is a pattern that can be matched by exception. The definition
63: /// must be redefined in including grammars.
64: def CommonControlFlow_ParameterPattern {
65: };
66: /// This is an utility definition of block body.
67: def CommonControlFlow_Body {
68: @ body = ref(CommonControlFlow_BlockFragment);
69: };
70: /// Redefine block fragment to refer to itself
71: def CommonControlFlow_BlockFragment {
72: ^ c:MethodBlock {
73: @ content += block;
74: };
75: };
76: /// This is a generic expression statement. The expression
77: /// executed in such way is supposed to have side effects.
78: /// For example, it can update local variable or invoke system
79: /// call.
80: statement ExpressionStatement {
81: ^ c:ExpressionStatement {
82: @ expression = ref(CommonControlFlow_GenericExpression);
83: };
84: };
85: /// Classical conditional statement almost only irregularity is that
86: /// "else if" is written as "elseif".
87: statement IfStatement {
88: ^ c:IfStatement {
89: @ ifThenPart += {
90: % if {
91: ^ c:IfThenPart {
92: ref(CommonControlFlow_ConditionFragment);
93: ref(CommonControlFlow_Body);
94: };
95: };
96: % elseif {
97: ^ c:IfThenPart {
98: ref(CommonControlFlow_ConditionFragment);
99: ref(CommonControlFlow_Body);
100: };
101: } *;
102: };
103: % else {
104: @ elsePart = ref(CommonControlFlow_BlockFragment);
105: } ?;
106: };
107: };
108: statement SwitchStatement {
109: ^ c:SwitchStatement {
110: % switch {
111: ref(CommonControlFlow_LabelFragment) ?;
112: %({
113: @ value = ref(CommonControlFlow_GenericExpression);
114: } %);
115: @ parts += block(CommonControlFlow_SwitchContent);
116: };
117: };
118: };
119: statement WhileStatement {
120: ^ c:WhileStatement {
121: % while {
122: ref(CommonControlFlow_LabelFragment) ?;
123: ref(CommonControlFlow_ConditionFragment);
124: ref(CommonControlFlow_Body);
125: };
126: };
127: };
128: statement DoWhileStatement {
129: ^ c:DoWhileStatement {
130: % do {
131: ref(CommonControlFlow_LabelFragment) ?;
132: ref(CommonControlFlow_Body);
133: };
134: % while {
135: ref(CommonControlFlow_ConditionFragment);
136: };
137: };
138: };
139: statement BreakStatement {
140: ^ c:BreakStatement {
141: % break {
142: ref(CommonControlFlow_LabelFragment) ?;
143: };
144: };
145: };
146: def CommonControlFlow_ContinueSwitchRef {
147: % case {
148: {
149: @ caseValue = ref(CommonControlFlow_GenericExpression);
150: } | {
151: @ defaultLabel = ^ c:SwitchDefaultPartRef {
152: % default {
153: };
154: };
155: };
156: };
157: };
158: statement ContinueStatement {
159: ^ c:ContinueStatement {
160: % continue {
161: {
162: ref(CommonControlFlow_LabelFragment);
163: ref(CommonControlFlow_ContinueSwitchRef) ?;
164: } | {
165: ref(CommonControlFlow_ContinueSwitchRef) ?;
166: };
167: };
168: };
169: };
170: statement ReturnStatement {
171: ^ c:ReturnStatement {
172: % return {
173: {
174: @ value = ref(CommonControlFlow_GenericExpression);
175: } ?;
176: };
177: };
178: };
179: statement ThrowStatement {
180: ^ c:ThrowStatement {
181: % throw {
182: @ exception = ref(CommonControlFlow_GenericExpression);
183: };
184: };
185: };
186: statement TryStatement {
187: ^ c:TryStatement {
188: % try {
189: ref(CommonControlFlow_Body);
190: };
191: {
192: % catch {
193: @ catchPart += ^ c:CatchPart {
194: @ specification = %({
195: ref(CommonControlFlow_ParameterPattern);
196: } %);
197: ref(CommonControlFlow_Body);
198: };
199: } +;
200: % finally {
201: @ finallyPart = ref(CommonControlFlow_BlockFragment);
202: } ?;
203: } | {
204: % finally {
205: @ finallyPart = ref(CommonControlFlow_BlockFragment);
206: };
207: };
208: };
209: };
210: statement ForeachStatement {
211: ^ c:ForeachStatement {
212: % foreach {
213: ref(CommonControlFlow_LabelFragment) ?;
214: %({
215: @ parameter = ref(CommonControlFlow_ParameterPattern);
216: % in {
217: @ collection = ref(CommonControlFlow_GenericExpression);
218: } | {
219: % from {
220: @ initial = ref(CommonControlFlow_GenericExpression);
221: };
222: % to {
223: @ limit = ref(CommonControlFlow_GenericExpression);
224: };
225: };
226: } %);
227: ref(CommonControlFlow_Body);
228: };
229: };
230: };
231: statement MethodBlock {
232: ref(CommonControlFlow_BlockFragment);
233: };
234: };
235: context abstract CommonControlFlow_SwitchContent {
236: include CommonControlFlow_Commons;
237: import CommonControlFlow = CommonControlFlow;
238: def CommonControlFlow_Body {
239: @ body = ^ c:MethodBlock {
240: @ content += block(CommonControlFlow);
241: };
242: };
243: statement SwitchCasePart {
244: ^ c:SwitchCasePart {
245: % case {
246: @ values += list, {
247: ref(CommonControlFlow_GenericExpression);
248: };
249: ref(CommonControlFlow_Body);
250: };
251: };
252: };
253: statement SwitchDefaultPart {
254: ^ c:SwitchDefaultPart {
255: % default {
256: ref(CommonControlFlow_Body);
257: };
258: };
259: };
260: };
261: };