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: 	// TODO change this grammar to use another namespace and better names for objects
    20: 	// FUTURE namespace c = "http://etl.sf.net/2006/samples/ej/CommonControlFlow";
    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: 		// Note the prefix "CommonControlFlow_" for definitions. Since
    39: 		// it is not known where this grammar will be used, this is done 
    40: 		// to avoid conflict with multiple includes from different grammars.
    41: 		// Less generic grammars do not need to follow such policy.
    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: };