All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jbase.Jbase.xtext Maven / Gradle / Ivy

There is a newer version: 0.12.2
Show newest version
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
;





© 2015 - 2024 Weber Informatics LLC | Privacy Policy