Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » [XBase] Extending XBase to support different call ids(Extending XBase to support different call ids)
[XBase] Extending XBase to support different call ids [message #1072416] Mon, 22 July 2013 18:07 Go to next message
Stefan Prisca is currently offline Stefan Prisca
Messages: 7
Registered: July 2013
Junior Member
Hi,
I have to write a DSL that supports JFace Template language syntax. This pretty much resumes to changing the syntax of call IDs of XBase feature calls to the template syntax. For instance String ${freeName(element)}; should stand for a variable declaration. I've wrote the grammar to support the syntax, but i'm having troubles with the code generation and scoping parts.

Currently the grammar looks like this [1] (sorry if it is too long, this is why i placed it at the end). I'm not sure it is in the best shape as i made some modifications to it while trying to solve the problems).
I had to extend some parts of XBase to put in my call IDs . I'm not sure it was the best way to do it.

I'm also using the JvmModelInferrer. It offers scoping for elements outside the method body only.
This looks like this:

def dispatch void infer(entity element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
   		
   	acceptor.accept( element.toClass( element.fullyQualifiedName )
   			 ).initializeLater [
     			 documentation = element.documentation
      				if (element.JType != null)
        			superTypes += element.JType.type.cloneWithProxies 
   				for (feature : element.features) {
   					switch feature{
   						attributeDeclaration 
   								:{ 
   									members+=feature.toField(feature.name.name, feature.JType.type)
   								}
   						method 
   								:{
          						  	members += feature.toMethod(feature.name, 
          						  		 if (feature.JType != null) feature.JType.type
          						  	) [
              						documentation = feature.documentation
              						for (p : feature.params) {
                					parameters += p.toParameter(p.name.name, p.JType.type)
              						}
             	 					body =  [
             	 	
             	 						for(blkFeature : feature.body.eContents)
             	 						{
             	 							switch(blkFeature){
             	 								
             	 								XExpression:
             	 									snipCompiler.toJavaStatement(blkFeature, it, true)						
             	 							}
             	 							
             	 						}
             	 					
             	 					]
             	 				]
   						}
   					
   				}
   		
   			]
   	}
}


Also, the specific compiler:

@SuppressWarnings("restriction")
public class SnipDSLSpecificCompiler extends XbaseCompiler {

	public void _toJavaStatement(XVariableDeclarationImpl expr, ITreeAppendable b, boolean isReferenced) {
		if (expr.getValue() != null) {
			//TODO: internalToJavaStatement(expr.getRight(), b, true);
		}
		b.newLine();
		appendVariableTypeAndName(expr, b);
		b.append(";");
	}
	protected JvmTypeReference appendVariableTypeAndName(XVariableDeclarationImpl varDeclaration, ITreeAppendable b) {
		JvmTypeReference type = null;
		if (varDeclaration.getJType() != null) {
			type = varDeclaration.getJType().getType();
		} 
		serialize(type, varDeclaration, b);
		b.append(" ");
		b.append(b.declareVariable(varDeclaration, makeJavaIdentifier(varDeclaration.getName().getName())));
		return type;
	}

	public void _toJavaStatement(XAssignmentImpl expr, ITreeAppendable b, boolean isReferenced) {
		if (expr.getValue() != null) {
			doInternalToJavaStatement(expr.getValue(), b, false);
		}
		b.newLine();
		if(expr.getFeature().getName().getAbstractName()!=null)
			b.append(expr.getFeature().getName().getAbstractName());
		else b.append(expr.getFeature().getName().getName().getSimpleName());
		b.append(expr.getOperator());
		if (expr.getValue() != null) {
			doInternalToJavaStatement(expr.getValue(), b, false);
			} else {
			appendDefaultLiteral(b, null);
		}
		b.append(";");
	}
	@Override
	protected void doInternalToJavaStatement(XExpression obj, ITreeAppendable appendable, boolean isReferenced) {
		if(obj instanceof XVariableDeclarationImpl)
		{
			this._toJavaStatement((XVariableDeclarationImpl)obj, appendable, isReferenced);
		} else if(obj instanceof XAssignmentImpl)
		{
			this._toJavaStatement((XAssignmentImpl)obj, appendable, isReferenced);
		}  else {
			super.doInternalToJavaStatement(obj, appendable, false);
		}
	}
	

}

This is used to generate the java code. It does not cover all the extended expressions from XBase, but i'm currently working on that.(If the solution to my problem comes from here, i must apologize for this post Smile )

Also, i override the runtime module to use my compiler:
public class SnipDSLRuntimeModule extends org.eclipse.recommenders.snipeditor.AbstractSnipDSLRuntimeModule {

	public Class<? extends XbaseCompiler> bindXbaseCompiler() {
		return SnipDSLSpecificCompiler.class;

	}
	
}


That being said, I need to provide scoping and code completion for elements inside the body of the method. This would include code proposals for declared methods, variables and all imported ones(pretty much like in a normal java program). I know that XText offers all this without any hard-work on the programmers side(as seen from the domainmodel example), but I am not sure how to do this in my case. I looked over the XBaseBatchScopeProvider and XBaseScopeProvider (as i understood from other forum posts, this are the classes i must extend) but i cannot figure it out.

Any help is highly appreciated Smile
Best Regards, Stefan.

[1]
grammar org.eclipse.recommenders.snipeditor.SnipDSL with org.eclipse.xtext.xbase.Xbase
import "http://www.eclipse.org/xtext/xbase/Xtype"
import 'http://www.eclipse.org/xtext/xbase/Xbase' as xbase
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types

generate snipDSL "http://www.eclipse.org/recommenders/snipeditor/SnipDSL"

domainmodel:
	importSection=XImportSection?
    (elements += abstractElement )*
;
XImportDeclaration :
	'${''import''('
	(
	importedType=[types::JvmDeclaredType|QualifiedName] 
		| importedNamespace=QualifiedNameWithWildcard
	)
	')}'
;


abstractElement returns xbase::XExpression:
	packageDeclare | 
	entity | 
	feature | 
	helpperClassAnnotation | 
	abstractAssignmentOperation ";"? |
	jFaceSpecificLiteral
;

packageDeclare:
	'package' name = QualifiedName '{'
	(elements += abstractElement)*
	'}'
;


entity:
	(visibility=Visibility)? 'class' name = ValidID 
		('extends' jType=abstractTypeName  )?
	'{'
		features += feature*
	
	'}'
;

feature returns xbase::XExpression:
	attributeDeclaration ";" | method 

;


parameter :
	(jType=abstractTypeName)  name = declarativeID;


method:
	(visibility=Visibility)? 'static'?  (jType=abstractTypeName | "void")
	name=ValidID'('(params+=parameter
		(','params+=parameter)*)?')' 
		('throws' throwExceptions+=simpleOperand(',' throwExceptions+=simpleOperand)*)?
	body=XBlockExpression
;
//attribute assignments
attributeAssignment returns xbase::XExpression:
	 arrayAssignment | blockAssignment | literal |=>XExpression
;
//assignment with {...}
blockAssignment:
	{blockAssignment}
	"{" (values+=literal (',' values+=literal)*)? "}"
;
//square bracket assignment
arrayAssignment:
	{arrayAssignment}
	"new" (jType=abstractTypeName) arguments=squareClosure
;



//attribute declaration
attributeDeclaration :
	(visible=Visibility)? 'static'? (jType=abstractTypeName)
	name = declarativeID ('=' value=attributeAssignment)? 
;

//expression of the block

//features that are present in the block
XExpressionInsideBlock  returns xbase::XExpression :
 			(XVariableDeclaration ';' | 
 			 abstractAssignmentOperation ';'? | 
			 jFaceSpecificLiteral
 			)
;

abstractAssignmentOperation returns xbase::XExpression:
	XExpression | unaryOperation
;

XAssignment returns xbase::XExpression :
	{XAssignment} feature=simpleOperand operator=valueAssignmentOperator value=XAssignment |	
	XOrExpression (
		=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpMultiAssign]) rightOperand=XAssignment
	)?;

XVariableDeclaration:
	jType=abstractTypeName
	name=declarativeID ('=' value = attributeAssignment)?
;

XMemberFeatureCall returns xbase::XExpression:
	XPrimaryExpression
	(=>({XAssignment.assignable=current} ('.'|explicitStatic?="::") feature=simpleOperand OpSingleAssign) value=XAssignment
	|=>({XMemberFeatureCall.memberCallTarget=current} ("."|nullSafe?="?."|explicitStatic?="::")) 
		('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')?  
		feature=simpleOperand (
			=>explicitOperationCall?='(' 
				(
				    memberCallArguments+=XShortClosure
				  |	memberCallArguments+=XExpression (',' memberCallArguments+=XExpression)*
				)? 
			')')?
			memberCallArguments+=XClosure?
		)*;
XFeatureCall returns XExpression:
	{XFeatureCall}
	('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')? 
	feature=simpleOperand 
	(=>explicitOperationCall?='(' 
		(
		    featureCallArguments+=XShortClosure
		  |	featureCallArguments+=XExpression (',' featureCallArguments+=XExpression)*
		)? 
	')')?
	featureCallArguments+=XClosure?;




simpleOperand:
	name = (operandID) 	
	(arguments+=squareClosure)?
;

unaryOperator:
	"++" | "--"
;
valueAssignmentOperator:
	"="|"+="|"-="
;
 
XForLoopExpression returns xbase::XExpression:
	
	classicForLoop | forLoopWithIterator
	;

classicForLoop:
	
	'for' '(' declaredParam=(XVariableDeclaration | simpleOperand) ';' 
				forExpression=XExpression ';'
				forOperation=abstractAssignmentOperation ')'
		body=XBlockExpression
;

forLoopWithIterator:
	'for''('
		jType=(abstractTypeName) iteratorName=declarativeID ':'
		iteratableObject=XExpression
		
	')'
	body=XBlockExpression
;

XConstructorCall returns xbase::XExpression:
	{XConstructorCall}
	'new' constructor=abstractTypeName 
	(=>'<' typeArguments+=abstractTypeName (',' typeArguments+=abstractTypeName)* '>')?
	(=>'(' 
		(
		    arguments+=XExpression
		    (',' arguments+=XExpression)*
		)? 
	')')?
	arguments+=squareClosure?;

XTryCatchFinallyExpression returns XExpression:
	{XTryCatchFinallyExpression}
	'try' 
		expression=XBlockExpression
	(
		catchClauses+=XCatchClause+
		(=>'finally' finallyExpression=XBlockExpression)?
	|	'finally' finallyExpression=XBlockExpression
	);
	
XCatchClause :
	=>'catch' '(' param=parameter ')' expression=XBlockExpression;




enum Visibility :
	 protected | public | private
;

//TODO: put abstract type in elemType!
 typeID:
 	{typeID}
 		('${'ValidID 
			(=>':''elemType' '('type=JvmTypeReference')}' | '}'))
 		|(=>'${''elemType' '('type=JvmTypeReference')}')
 ;

declarativeID:
	  jFaceVarID |
	  => name=ValidID 
;

jFaceVarID :
	{jFaceVarID}
 		'${'name=ValidID'}' 
		|(=>'{' ValidID':'('freeName'|'newName') '('name=ValidID')}')
 		|(=>'${'('freeName'|'newName') '('name=ValidID')}')
;
operandID :
	 
	name=[types::JvmIdentifiableElement|ValidID] | 
	 ('${' abstractName=ValidID ':''var''}') 
	 |=>'${'abstractName=ValidID'}'
	|=>abstractName=ValidID//remove this when possible
;
FeatureCallID:
	ValidID | 'extends' | 'static' | 'import' | 'extension'
;


literal:
	value= (STRING | Number | booleanLiteral  )
;
booleanLiteral:
	'true' | 'false' | 'null'
;

jFaceSpecificLiteral:
	'${'type=('cursor'|'dollar'|'line_selection')'}'
;

abstractTypeName :
	(typeID) '[]'? 
	|=>	type=JvmTypeReference '[]'?
;
helpperClassAnnotation :
	'${' 'helper' '}' 
	class= entity 
	'${' 'endHelper' '}'
;

squareClosure returns xbase::XExpression:
	'[' XExpression ']'
;
 

Re: [XBase] Extending XBase to support different call ids [message #1074210 is a reply to message #1072416] Fri, 26 July 2013 09:35 Go to previous message
Stefan Prisca is currently offline Stefan Prisca
Messages: 7
Registered: July 2013
Junior Member
Hello again,
I managed to solve this problem by setting the method body in the JvmModelInferrer to the following:
 body = feature.body 
and using a costume type computer for the extended Xbase expressions along with the specific compiler Smile
Also i made some changes in the grammar. Instead of re-writing the expressions, i changed the FeatureCallID rule from XBase only, thus changing only the ids.
Maybe this helps if anyone has a similar problem Smile

Best Regards, Stefan.
Previous Topic:ClassNotFoundException: org.eclipse.xtext.ecore.ecoresupportstandalonesetup
Next Topic:xtext unusably slow for editing and building certain kinds of grammars
Goto Forum:
  


Current Time: Thu Oct 23 11:21:50 GMT 2014

Powered by FUDForum. Page generated in 0.09446 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software