jbase.Jbase.xtext Maven / Gradle / Ivy
grammar jbase.Jbase with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations
//generate jbase "http://www.Jbase.jbase"
import "http://www.Jbase.jbase"
import "http://www.eclipse.org/xtext/xbase/Xtype" as xtype
import "http://www.eclipse.org/xtext/xbase/Xbase"
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types
/**
* The syntactic predicate on XBlockExpression is required to avoid
* ambiguity with array literal. However, XBlockExpression must come first, to
* be able to parse both while(...) {} and while(...) st; for example.
* If we put the predicate on single statement, then it does not seem to
* be possible to parse incomplete member feature call.
*/
XJStatementOrBlock returns XExpression:
// XJArrayConstructorCall | not a valid statement
=>XBlockExpression |
XJSingleStatement
;
/**
* Customize to reflect Java imports (e.g., no 'extension' keyword and mandatory ';' but many occurrences accepted)
*/
@Override
XImportDeclaration returns xtype::XImportDeclaration:
(=>'import' (
(static?='static' importedType=[types::JvmDeclaredType|QualifiedNameInStaticImport] (wildcard?='*' | memberName=ValidID))
| importedType=[types::JvmDeclaredType|QualifiedName]
| importedNamespace=QualifiedNameWithWildcard) ->';'*)
;
@Override
JvmTypeReference returns types::JvmTypeReference:
JvmParameterizedTypeReference =>({types::JvmGenericArrayTypeReference.componentType=current} ArrayBrackets)*
// | XFunctionTypeRef;
;
// customized with 'final' specification and varargs
@Override
FullJvmFormalParameter returns XJJvmFormalParameter:
{XJJvmFormalParameter} final?='final'? parameterType=JvmTypeReference varArgs?='...'? name=ValidID;
XJSingleStatement returns XExpression:
XJSemicolonStatement |
XSwitchExpression |
XIfExpression |
XForLoopExpression |
XBasicForLoopExpression |
XWhileExpression |
XJTryWithResourcesStatement |
XTryCatchFinallyExpression |
XSynchronizedExpression |
XJEmptyStatement
;
/*
* These are the Java statements that require a semicolon at the end.
*
* The final ; is optional in order to be able to parse incomplete
* expressions, provide nicer error messages and give better content assist.
* The presence of ';' is checked by the validator
*/
XJSemicolonStatement returns XExpression:
{XJSemicolonStatement}
expression=
(
XJBranchingStatement |
XExpressionOrVarDeclaration |
XDoWhileExpression |
XReturnExpression |
XThrowExpression
)
->semicolon=';'?
;
XJEmptyStatement returns XExpression:
{XJSemicolonStatement} semicolon=';'
;
XJBranchingStatement returns XExpression:
{XJContinueStatement} "continue" |
{XJBreakStatement} "break"
;
/*
* The semicolons ';' are handled by the XJSemicolonStatement rule
*/
@Override
XBlockExpression returns XExpression:
{XBlockExpression}
'{'
(expressions+=XJStatementOrBlock)*
'}';
// Don't put the predicate in the rule for XExpressionOrVarDeclaration:
// it would break partial parsing:
// "int i =" would not be parsed as an incomplete variable declaration
// put the predicate in XVariableDeclaration rule directly
//XExpressionOrVarDeclaration returns XExpression:
// =>XVariableDeclaration | XExpression;
// Use the predicate to avoid ambiguities with XExpression
@Override
XVariableDeclaration returns XVariableDeclaration:
=>({XJVariableDeclaration}
final?='final'?
type=JvmTypeReference name=ValidID) ('=' right=XExpression)?
(=>',' additionalVariables+=XJAdditionalXVariableDeclaration)*;
// the second predicate is to avoid ambiguities with for loops
// that already consider several variable declarations
// in our case we always parse them as several variable declarations
// since we allow them also as standard variable declarations as in Java
XJAdditionalXVariableDeclaration returns XVariableDeclaration:
{XJAdditionalXVariableDeclaration}
name=ValidID ('=' right=XExpression)?;
@Override
XAssignment returns XExpression :
=>({XJAssignment} feature=[types::JvmIdentifiableElement|FeatureCallID]
'[' indexes+=XExpression ']'('[' indexes+=XExpression ']')*
OpSingleAssign) value=XAssignment |
=>({XAssignment} feature=[types::JvmIdentifiableElement|FeatureCallID]
OpSingleAssign) value=XAssignment |
XOrExpression (
=>({XJConditionalExpression.if=current} '?') then=XExpression ':' else=XExpression
|
=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpMultiAssign]) rightOperand=XAssignment
)?;
@Override
OpMultiAssign:
'+=' | '-=' | '*=' | '/=' | '%=' |
'&=' | '|=' | '^=' | // added in Jbase
'<' '<' '=' |
'>' '>'? '>=';
XJFeatureCallWithArrayAccess returns XExpression:
XFeatureCall (
=>({XJArrayAccessExpression.array=current}
'[' indexes+=XExpression ']' (=>'[' indexes+=XExpression ']')*)
)?
;
@Override
XFeatureCall returns XExpression:
{XFeatureCall}
feature=[types::JvmIdentifiableElement|IdOrSuper]
(=>explicitOperationCall?='('
(
featureCallArguments+=XExpression (',' featureCallArguments+=XExpression)*
)?
')'
)?;
// also record '<' to tell whether it's a diamond operator
@Override
XConstructorCall returns XExpression:
{XJConstructorCall}
'new' constructor=[types::JvmConstructor|QualifiedName]
(=>explicitTypeArguments?='<' (typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)*)? '>')?
(=>explicitConstructorCall?='('
(
arguments+=XExpression (',' arguments+=XExpression)*
)?
')')?;
// dimensions and dimension expressions (feature indexes) are not associated during parsing,
// the association, i.e., knowing whether a dimension expression comes after
// an empty dimension (which is not legal), will be retrieved by
// JbaseModelUtil.arrayDimensionIndexAssociations(XJArrayConstructorCall)
// based on the offset of the [ and the array dimension XEpression
XJArrayConstructorCall returns XExpression:
=>({XJArrayConstructorCall}
'new'
type=[types::JvmType|QualifiedName] dimensions+=XJArrayDimension)
// getting here is enough to tell it's an array constructor call
(indexes+=XExpression)? ']'
(=>dimensions+=XJArrayDimension (indexes+=XExpression)? ']')*
(=>arrayLiteral=XJArrayLiteral)?
;
// We need an EObject instead of a simple String since we then
// need to find the corresponding node (and offset) with NodeModelUtils
// in order to associate dimensions with indexes
XJArrayDimension:
{XJArrayDimension} '['
;
@Override
XCastedExpression returns XExpression:
=>({XCastedExpression} '(' type=JvmTypeReference ')' target=XExpression)
|
XPostfixOperation
;
@Override
XPostfixOperation returns XExpression:
=>({XJPrefixOperation} feature=[types::JvmIdentifiableElement|OpPostfix]) operand=XMemberFeatureCall
|
XMemberFeatureCall
(
=>({XPostfixOperation.operand=current} feature=[types::JvmIdentifiableElement|OpPostfix])
|
=>({XJArrayAccessExpression.array=current} '[' indexes+=XExpression ']'(=>'[' indexes+=XExpression ']')*)
)?
;
@Override
XMemberFeatureCall returns XExpression:
XPrimaryExpression
(
// we don't need this at the moment
// =>({XJAssignment.assignable=current} ('.'|explicitStatic?="::")
// feature=[types::JvmIdentifiableElement|FeatureCallID]
// '[' index=XExpression ']'
// OpSingleAssign) value=XAssignment
// |
=>({XJClassObject.typeExpression=current} (arrayDimensions+=ArrayBrackets)* '.' 'class')
|
=>({XAssignment.assignable=current} '.'
feature=[types::JvmIdentifiableElement|FeatureCallID] OpSingleAssign)
value=XAssignment
|
=>({XMemberFeatureCall.memberCallTarget=current} ".")
feature=[types::JvmIdentifiableElement|IdOrSuper] (
=>explicitOperationCall?='('
(
memberCallArguments+=XExpression (',' memberCallArguments+=XExpression)*
)?
')')?
)*;
// in Java the type must be specified so we must use FullJvmFormalParameter instead of JvmFormalParameter
@Override
XForLoopExpression returns XExpression:
=>({XForLoopExpression}
'for' '(' declaredParam=FullJvmFormalParameter ':') forExpression=XExpression ')'
eachExpression=XJStatementOrBlock;
@Override
XBasicForLoopExpression returns XExpression:
{XBasicForLoopExpression}
'for' '('(initExpressions+=XExpressionOrVarDeclaration (',' initExpressions+=XExpressionOrVarDeclaration)*)? ';'
expression=XExpression? ';'
(updateExpressions+=XExpression (',' updateExpressions+=XExpression)*)? ')'
eachExpression=XJStatementOrBlock;
@Override
XIfExpression returns XExpression:
{XIfExpression}
'if' '(' if=XExpression ')'
then=XJStatementOrBlock
(=>'else' else=XJStatementOrBlock)?;
@Override
XWhileExpression returns XExpression:
{XWhileExpression}
'while' '(' predicate=XExpression ')'
body=XJStatementOrBlock;
@Override
XDoWhileExpression returns XExpression:
{XDoWhileExpression}
'do'
body=XJStatementOrBlock
'while' '(' predicate=XExpression ')';
@Override
XSwitchExpression returns XExpression:
{XSwitchExpression}
'switch' '(' switch=XExpression ')' '{'
(cases+=XCasePart)*
('default' ':' default=XJSwitchStatements )?
'}';
@Override
XCasePart:
{XCasePart}
'case' case=XExpression
':' then=XJSwitchStatements;
/**
* Java switch's case expression does not require an explicit block { }
*/
XJSwitchStatements returns XExpression:
{XJSwitchStatements}
(expressions+=XJStatementOrBlock)*
;
/**
* Java 7 try-with-resources
*/
XJTryWithResourcesStatement returns XExpression:
=>({XJTryWithResourcesStatement} 'try' openParenthesis?='(')
resourceDeclarations+=XJTryWithResourcesVariableDeclaration*
')'
expression=XBlockExpression
catchClauses+=XCatchClause*
('finally' finallyExpression=XBlockExpression)?
;
/*
* The final ; is optional in the last variable declaration in a
* try-with-resources
*/
XJTryWithResourcesVariableDeclaration:
{XJTryWithResourcesVariableDeclaration}
final?='final'?
type=JvmTypeReference name=ValidID '=' right=XExpression
semicolon=';'?
;
/**
* Java needs blocks for try, catch, finally
*/
@Override
XTryCatchFinallyExpression returns XExpression:
{XTryCatchFinallyExpression}
'try'
expression=XBlockExpression
(
catchClauses+=XCatchClause+
(=>'finally' finallyExpression=XBlockExpression)?
| 'finally' finallyExpression=XBlockExpression
);
// the explicit {XCatchClause} is required to make formatting work
@Override
XCatchClause :
{XCatchClause} =>'catch' '(' declaredParam=FullJvmFormalParameter ')' expression=XBlockExpression;
/**
* Java needs block for synchronized
*/
@Override
XSynchronizedExpression returns XExpression:
=>({XSynchronizedExpression}
'synchronized' '(') param=XExpression ')' expression=XBlockExpression;
@Override
XPrimaryExpression returns XExpression:
XJArrayConstructorCall |
XConstructorCall |
// XBlockExpression |
// XSwitchExpression |
// XSynchronizedExpression |
XJFeatureCallWithArrayAccess |
XLiteral |
// XIfExpression |
// XForLoopExpression |
// XBasicForLoopExpression |
// XWhileExpression |
// XDoWhileExpression |
// XThrowExpression |
// XReturnExpression |
// XTryCatchFinallyExpression |
XParenthesizedExpression;
@Override
XLiteral returns XExpression:
// XCollectionLiteral |
// XClosure |
XBooleanLiteral |
XNumberLiteral |
XNullLiteral |
XCharLiteral |
XStringLiteral |
XJArrayLiteral
// XTypeLiteral
;
// it is a subclass of XListLiteral, so that we will reuse
// type computation and compiler from Xbase
XJArrayLiteral returns XJArrayLiteral:
{XJArrayLiteral} '{' (elements+=XExpression (',' elements+=XExpression )*)? '}'
;
/*
* We want to tell between string and char literals since we'll treat them
* differently from the type computation point of view.
*/
XCharLiteral returns XExpression:
{XJCharLiteral} value=CHARACTER;
@Override
XStringLiteral returns XExpression:
{XStringLiteral} value=STRING;
@Override
terminal STRING:
'"' ( '\\' . /* ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') */ | !('\\'|'"') )* '"'?;
terminal CHARACTER:
"'" ( '\\' . /* ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') */ | !('\\'|"'") )* "'"?;
@Override
OpEquality:
'==' | '!=' ;
// '**' is not valid in Java
@Override
OpMulti:
'*' | '/' | '%';
// only valid Java operators
@Override
OpOther:
'>' (=>('>' '>') | '>')
| '<<';
// add bitwise operators with their precedence
@Override
XAndExpression returns XExpression:
XBitwiseInclusiveOrExpression (=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpAnd]) rightOperand=XBitwiseInclusiveOrExpression)*;
XBitwiseInclusiveOrExpression returns XExpression:
XBitwiseExclusiveOrExpression (=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpInclusiveOr]) rightOperand=XBitwiseExclusiveOrExpression)*;
OpInclusiveOr:
'|';
XBitwiseExclusiveOrExpression returns XExpression:
XBitwiseAndExpression (=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpExclusiveOr]) rightOperand=XBitwiseAndExpression)*;
OpExclusiveOr:
'^';
XBitwiseAndExpression returns XExpression:
XEqualityExpression (=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpBitwiseAnd]) rightOperand=XEqualityExpression)*;
OpBitwiseAnd:
'&';
// add bitwise not ~
@Override
OpUnary:
"!" | "-" | "+" | "~";
// customization of multiple values for annotations to use the Java array literal syntax
@Override
XAnnotationElementValueOrCommaList returns XExpression:
=>({XJArrayLiteral} '{') (elements+=XAnnotationOrExpression (',' elements+=XAnnotationOrExpression )*)? '}'
| XAnnotationOrExpression // in Java multiple values must be specified with an array literal
// ({XListLiteral.elements+=current} (',' elements+=XAnnotationOrExpression )+)?
;
@Override
XAnnotationElementValue returns XExpression :
=>({XJArrayLiteral} '{') (elements+=XAnnotationOrExpression (',' elements+=XAnnotationOrExpression )*)? '}'
| XAnnotationOrExpression
;