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: };