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