blob: 12502b6531e6ea6f1fc05a0da77d49cb82f7f4eb [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2010 E.D.Willink and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: EssentialOCL.xtext,v 1.14 2011/05/21 14:55:09 ewillink Exp $
*/
grammar org.eclipse.ocl.examples.xtext.essentialocl.EssentialOCL hidden(WS, ML_COMMENT, SL_COMMENT) //with org.eclipse.xtext.common.Terminals
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.eclipse.org/ocl/3.1.0/Pivot" as pivot
import "http://www.eclipse.org/ocl/3.1.0/BaseCST" as base
import "http://www.eclipse.org/ocl/3.1.0/EssentialOCLCST"
//generate essentialOCLCST "http://www.eclipse.org/ocl/3.0.0/EssentialOCLCST"
Model returns ContextCS:
ownedExpression=ExpCS;
terminal fragment ESCAPED_CHARACTER:
'\\' ('b' | 't' | 'n' | 'f' | 'r' | 'u' | '"' | "'" | '\\');
terminal fragment LETTER_CHARACTER:
'a'..'z' | 'A'..'Z' | '_';
terminal DOUBLE_QUOTED_STRING:
'"' (ESCAPED_CHARACTER | !('\\' | '"'))* '"';
terminal SINGLE_QUOTED_STRING:
"'" (ESCAPED_CHARACTER | !('\\' | "'"))* "'";
terminal ML_SINGLE_QUOTED_STRING:
"/'"->"'/";
terminal SIMPLE_ID:
LETTER_CHARACTER (LETTER_CHARACTER | ('0'..'9'))*;
terminal ESCAPED_ID:
"_" SINGLE_QUOTED_STRING;
ID: SIMPLE_ID | ESCAPED_ID;
terminal INT: // String to allow diverse re-use
('0'..'9')+; // multiple leading zeroes occur as floating point fractional part
LOWER returns ecore::EInt:
INT
;
UPPER returns ecore::EInt:
INT | '*'
;
NUMBER_LITERAL returns BigNumber: // Not terminal to allow parser backtracking to sort out "5..7"
INT; // EssentialOCLTokenSource pieces this together ('.' INT)? (('e' | 'E') ('+' | '-')? INT)?;
terminal ML_COMMENT:
'/*' ->'*/';
terminal SL_COMMENT:
'--' !('\n' | '\r')* ('\r'? '\n')?;
terminal WS:
(' ' | '\t' | '\r' | '\n')+;
terminal ANY_OTHER:
.;
URI:
SINGLE_QUOTED_STRING;
EssentialOCLReservedKeyword:
'and'
| 'else'
| 'endif'
| 'if'
| 'implies'
| 'in'
| 'let'
| 'not'
| 'or'
| 'then'
| 'xor';
EssentialOCLUnaryOperatorCS returns UnaryOperatorCS:
name=('-' | 'not');
EssentialOCLInfixOperatorCS returns BinaryOperatorCS:
name=('*' | '/' | '+' | '-' | '>' | '<' | '>=' | '<=' | '=' | '<>' | 'and' | 'or' | 'xor' | 'implies');
EssentialOCLNavigationOperatorCS returns NavigationOperatorCS:
name=('.' | '->');
Identifier:
ID;
StringLiteral:
SINGLE_QUOTED_STRING;
BinaryOperatorCS returns BinaryOperatorCS:
InfixOperatorCS | NavigationOperatorCS;
InfixOperatorCS returns BinaryOperatorCS: // Intended to be overrideable
EssentialOCLInfixOperatorCS;
NavigationOperatorCS returns NavigationOperatorCS: // Intended to be overrideable
EssentialOCLNavigationOperatorCS;
UnaryOperatorCS returns UnaryOperatorCS: // Intended to be overrideable
EssentialOCLUnaryOperatorCS;
//---------------------------------------------------------------------
// Names
//---------------------------------------------------------------------
EssentialOCLUnrestrictedName returns ecore::EString:
Identifier;
UnrestrictedName returns ecore::EString: // Intended to be overridden
EssentialOCLUnrestrictedName;
EssentialOCLUnreservedName returns ecore::EString:
UnrestrictedName
| CollectionTypeIdentifier
| PrimitiveTypeIdentifier
| 'Tuple'
;
UnreservedName returns ecore::EString: // Intended to be overridden
EssentialOCLUnreservedName;
PathNameCS returns base::PathNameCS:
path+=FirstPathElementCS ('::' path+=NextPathElementCS)*;
FirstPathElementCS returns base::PathElementCS:
element=[pivot::NamedElement|UnrestrictedName];
NextPathElementCS returns base::PathElementCS:
element=[pivot::NamedElement|UnreservedName];
URIPathNameCS returns base::PathNameCS:
path+=URIFirstPathElementCS ('::' path+=NextPathElementCS)*;
URIFirstPathElementCS returns base::PathElementCS:
element=[pivot::NamedElement|UnrestrictedName] | {base::PathElementWithURICS} element=[pivot::Namespace|URI];
//---------------------------------------------------------------------
// Types
//---------------------------------------------------------------------
PrimitiveTypeIdentifier:
'Boolean'
| 'Integer'
| 'Real'
| 'String'
| 'UnlimitedNatural'
| 'OclAny'
| 'OclInvalid'
| 'OclVoid';
PrimitiveTypeCS returns base::PrimitiveTypeRefCS:
name=PrimitiveTypeIdentifier;
CollectionTypeIdentifier returns ecore::EString:
'Set'
| 'Bag'
| 'Sequence'
| 'Collection'
| 'OrderedSet';
CollectionTypeCS returns CollectionTypeCS:
name=CollectionTypeIdentifier ('(' ownedType=TypeExpCS ')')?;
MultiplicityBoundsCS returns base::MultiplicityBoundsCS:
lowerBound=LOWER ('..' upperBound=UPPER)?;
MultiplicityCS returns base::MultiplicityCS:
'[' (MultiplicityBoundsCS | MultiplicityStringCS) ']';
MultiplicityStringCS returns base::MultiplicityStringCS:
stringBounds=('*'|'+'|'?');
TupleTypeCS returns base::TupleTypeCS:
name='Tuple' ('(' (ownedParts+=TuplePartCS (',' ownedParts+=TuplePartCS)*)? ')')?;
TuplePartCS returns base::TuplePartCS:
name=UnrestrictedName ':' ownedType=TypeExpCS;
//---------------------------------------------------------------------
// Literals
//---------------------------------------------------------------------
CollectionLiteralExpCS returns CollectionLiteralExpCS:
ownedType=CollectionTypeCS
'{' (ownedParts+=CollectionLiteralPartCS
(',' ownedParts+=CollectionLiteralPartCS)*)?
'}';
CollectionLiteralPartCS returns CollectionLiteralPartCS:
expressionCS=ExpCS ('..' lastExpressionCS=ExpCS)?;
ConstructorPartCS returns ConstructorPartCS:
property=[pivot::Property|UnrestrictedName] '=' initExpression=ExpCS;
PrimitiveLiteralExpCS returns PrimitiveLiteralExpCS:
NumberLiteralExpCS
| StringLiteralExpCS
| BooleanLiteralExpCS
| UnlimitedNaturalLiteralExpCS
| InvalidLiteralExpCS
| NullLiteralExpCS;
TupleLiteralExpCS returns TupleLiteralExpCS:
'Tuple' '{' ownedParts+=TupleLiteralPartCS (',' ownedParts+=TupleLiteralPartCS)* '}';
TupleLiteralPartCS returns TupleLiteralPartCS:
name=UnrestrictedName (':' ownedType=TypeExpCS)? '=' initExpression=ExpCS;
NumberLiteralExpCS returns NumberLiteralExpCS:
name=NUMBER_LITERAL;
StringLiteralExpCS returns StringLiteralExpCS:
name+=StringLiteral+;
BooleanLiteralExpCS returns BooleanLiteralExpCS:
name='true'
| name='false';
UnlimitedNaturalLiteralExpCS returns UnlimitedNaturalLiteralExpCS:
{UnlimitedNaturalLiteralExpCS} '*';
InvalidLiteralExpCS returns InvalidLiteralExpCS:
{InvalidLiteralExpCS} 'invalid';
NullLiteralExpCS returns NullLiteralExpCS:
{NullLiteralExpCS} 'null';
TypeLiteralCS returns base::TypedRefCS:
PrimitiveTypeCS
| CollectionTypeCS
| TupleTypeCS;
TypeLiteralWithMultiplicityCS returns base::TypedRefCS:
TypeLiteralCS multiplicity=MultiplicityCS?;
TypeLiteralExpCS returns TypeLiteralExpCS:
ownedType=TypeLiteralWithMultiplicityCS;
TypeNameExpCS returns TypeNameExpCS:
pathName=PathNameCS;
TypeExpCS returns base::TypedRefCS:
(TypeNameExpCS | TypeLiteralCS) multiplicity=MultiplicityCS?;
//---------------------------------------------------------------------
// Expressions
//---------------------------------------------------------------------
// An ExpCS permits a LetExpCS only in the final term to ensure
// that let is right associative, whereas infix operators are left associative.
// a = 64 / 16 / let b : Integer in 8 / let c : Integer in 4
// is
// a = (64 / 16) / (let b : Integer in 8 / (let c : Integer in 4 ))
ExpCS returns ExpCS:
(PrefixedExpCS
({InfixExpCS.ownedExpression+=current} ownedOperator+=BinaryOperatorCS
( (ownedExpression+=PrefixedExpCS
(ownedOperator+=BinaryOperatorCS ownedExpression+=PrefixedExpCS)*
(ownedOperator+=BinaryOperatorCS ownedExpression+=LetExpCS)?
)
| (ownedExpression+=LetExpCS)
)
)?
)
| ({PrefixExpCS} ownedOperator+=UnaryOperatorCS+ ownedExpression=LetExpCS)
| LetExpCS;
PrefixedExpCS returns ExpCS:
({PrefixExpCS} ownedOperator+=UnaryOperatorCS+ ownedExpression=PrimaryExpCS)
| PrimaryExpCS;
PrimaryExpCS returns ExpCS:
NestedExpCS
| IfExpCS
| SelfExpCS
| PrimitiveLiteralExpCS
| TupleLiteralExpCS
| CollectionLiteralExpCS
| TypeLiteralExpCS
| ({NameExpCS} pathName=PathNameCS
(
(({IndexExpCS.nameExp=current} '[' firstIndexes+=ExpCS (',' firstIndexes+=ExpCS)* ']'
('[' secondIndexes+=ExpCS (',' secondIndexes+=ExpCS)* ']')?
(atPre?='@' 'pre')?
))
|
({ConstructorExpCS.nameExp=current} '{'
( (ownedParts+=ConstructorPartCS (',' ownedParts+=ConstructorPartCS)*)
| (value=StringLiteral)
) '}'
)
| ( (atPre?='@' 'pre')?
({InvocationExpCS.nameExp=current} '(' (
argument+=NavigatingArgCS (argument+=NavigatingCommaArgCS)*
(argument+=NavigatingSemiArgCS (argument+=NavigatingCommaArgCS)*)?
(argument+=NavigatingBarArgCS (argument+=NavigatingCommaArgCS)*)?
)? ')'
)?
)
)
);
NavigatingArgCS returns NavigatingArgCS:
name=NavigatingArgExpCS (':' ownedType=TypeExpCS ('=' init=ExpCS)?)?; // Type-less init is an illegal infix expression
NavigatingBarArgCS returns NavigatingArgCS:
prefix='|' name=NavigatingArgExpCS (':' ownedType=TypeExpCS ('=' init=ExpCS)?)?; // Type-less init is an illegal infix expression
NavigatingCommaArgCS returns NavigatingArgCS:
prefix=',' name=NavigatingArgExpCS (':' ownedType=TypeExpCS ('=' init=ExpCS)?)?; // Type-less init is an illegal infix expression
NavigatingSemiArgCS returns NavigatingArgCS:
prefix=';' name=NavigatingArgExpCS (':' ownedType=TypeExpCS ('=' init=ExpCS)?)?; // Type-less init is an illegal infix expression
NavigatingArgExpCS returns ExpCS: // Intended to be overridden
ExpCS
// '?' -- defined by Complete OCL
;
IfExpCS returns IfExpCS:
'if' condition=ExpCS
'then' thenExpression=ExpCS
'else' elseExpression=ExpCS
'endif';
LetExpCS returns LetExpCS:
'let' variable+=LetVariableCS (',' variable+=LetVariableCS)*
'in' in=ExpCS;
LetVariableCS returns LetVariableCS:
name=UnrestrictedName (':' ownedType=TypeExpCS)? '=' initExpression=ExpCS;
NestedExpCS returns NestedExpCS:
'(' source=ExpCS ')';
SelfExpCS returns SelfExpCS:
{SelfExpCS} 'self';