Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Grammar & Scoping Pattern for variables, functions
Grammar & Scoping Pattern for variables, functions [message #736199] Thu, 13 October 2011 15:36 Go to next message
Matt Campbell is currently offline Matt Campbell
Messages: 11
Registered: April 2011
Junior Member
Hey folks! I'm working on a new xtext2-based project to describe basic scripted actions and workflows and I've been looking all over for a pattern to model scope access of subproperties through variable references. Think objects with attributes and functions. So I might have an object called "Database" that has a child object called "Table" that has some actions that can be performed on it.

My test grammar:
Model:
	(resources+=Resource
	| variables+=VariableDeclaration
	| actions+=ActionStatement)*
;
	
Resource:
	'resource' name=ID '{'
		(children+=Resource
		| actions+=ActionDeclaration)*
	'}'
;

ActionDeclaration:
	'action' name=ID '(' ')'
;

VariableDeclaration:
	'var' name=ID '=' resource=[Resource|QualifiedName]
;

ActionStatement:
	action=[ActionDeclaration|QualifiedName]
;

QualifiedName:
	ID ('.' ID)*;


This allows for models that look something like:
resource Database {
	resource Table {
		action selectAll()
		action runReport()
	}
	
	action listTables()	
}

var db = Database


My question is how to get the ActionStatement to behave how you'd expect in an object-oriented kind of way using the variable as a reference. As it sits in the grammar now, the editor will allow things like
Database.listTables()
Database.Table.selectAll()


Instead, I'd like it to do things like
db.listTables()
db.Table.selectAll()


I've been reading the documentation and the forums looking for examples of doing this with the scope API, and I briefly tried changing ActionStatement to the following:
ActionStatement:
	variable=[VariableDeclaration] '.' action=[ActionDeclaration]
;


I implemented the methods "scope_ActionStatement_variable(...)" and scope_ActionStatement_action(...)" to only offer actions visible as children under defined variables. This allowed "db.listTables()", but did not allow for arbitrarily traversing child resources to get to an action lower down in the tree.

So the short of it: using the scope API or grammar changes, how do I get the editor to treat variable declarations like the resource itself in resolving qualified references to children or actions? As always, thanks so much for the help!
Re: Grammar & Scoping Pattern for variables, functions [message #736235 is a reply to message #736199] Thu, 13 October 2011 16:58 Go to previous messageGo to next message
Christian Dietrich is currently online Christian Dietrich
Messages: 6198
Registered: July 2009
Senior Member
Hi,

you find the/an basic idea described here: http://dslmeinte.wordpress.com/2010/08/16/path-expressions-in-entity-models/

~Christian

[Updated on: Thu, 13 October 2011 17:01]

Report message to a moderator

Re: Grammar & Scoping Pattern for variables, functions [message #736948 is a reply to message #736235] Fri, 14 October 2011 09:51 Go to previous messageGo to next message
Matt Campbell is currently offline Matt Campbell
Messages: 11
Registered: April 2011
Junior Member
That's exactly what I was looking for. For anyone else curious in the future, I massaged the example a bit to come out with the following grammar:
grammar com.srcinc.testbed.variablescoping.VariableScopingDsl with org.eclipse.xtext.common.Terminals

generate variableScopingDsl "http://www.srcinc.com/testbed/variablescoping/VariableScopingDsl"

Model:
	(resources+=Resource
	| variables+=VariableDeclaration
	| actions+=ActionStatement)*
;
	
Resource:
	'resource' name=ID '{'
		(children+=Resource
		| actions+=ActionDeclaration)*
	'}'
;

ActionDeclaration:
	'action' name=ID '(' ')'
;

VariableDeclaration:
	'var' name=ID '=' resource=[Resource|QualifiedName]
;

ResourcePathHead:
	variable=[VariableDeclaration] (path=ResourcePathTail)?
;

ResourcePathTail:
	'/' childResource=[Resource] (path=ResourcePathTail)?
;

ActionStatement:
	path=ResourcePathHead ':' action=[ActionDeclaration]
;

QualifiedName:
	ID ('.' ID)*;


The scope provider is set up as below:
public IScope scope_ResourcePathTail_childResource(ResourcePathTail context, EReference ref) {
	EObject parent = context.eContainer();
    // parent can be ResourcePathHead or ResourcePathTail

    if(parent instanceof ResourcePathHead) {
        return scopeFor(((ResourcePathHead)parent).getVariable().getResource().getChildren());
    }
    if(parent instanceof ResourcePathTail) {
        Resource prevResource = ((ResourcePathTail)parent).getChildResource();
        return scopeFor(prevResource.getChildren());
    }

    // Fall-through? Probably a programmer error...
    throw new RuntimeException("don't know how to compute scope for 'feature' of PathTail");
}

public IScope scope_ActionStatement_action(final ActionStatement context, EReference ref) {
	//get the tail end of the resource path
	Resource tailResource = context.getPath().getVariable().getResource();
	ResourcePathTail currTail = context.getPath().getPath();
	while (null != currTail) {
		tailResource = currTail.getChildResource();
		currTail = currTail.getPath();
	}
	
	return scopeFor(tailResource.getActions());
}


This allows for syntax like the following:
var db = Database

db/Table: selectAll
db: listTables


I initially tried to use '.' as my separator for everything for a more Java-like path style, but I couldn't seem to resolve the ambiguities in the grammar between that and the method call itself and the qualified names. This is fine for my purposes though - thanks for the help!
Re: Grammar & Scoping Pattern for variables, functions [message #739369 is a reply to message #736199] Mon, 17 October 2011 07:55 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte Boersma
Messages: 433
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
You've got a few challenges at the same time here.

First of all, there's contention between QualifiedName (a datatype rule) and any rule which is allowed to gobble up an ID after a '.'. You could resolve this but in the process you'll probably be promoting each path element to a separate model element instead of gobbling them all up into one String - this could even be a good thing if you need a hook to exert some control/validation over the path elements themselves. Otherwise, the parser just has no way to know whether a following ".yaddaYadda" should be part of a QualifiedName or whether it corresponds to some nested Resource or ActionDeclaration.

Secondly, the parser also can't decide between two rules if both of these consume an ID which is the name of a cross-referrable thing. As a solution, you can use the "=[ecore::EObject]" trick from: http://dslmeinte.wordpress.com/2010/12/08/getting-alternative-cross-references-to-work-with-existing-epackages/ The price is that your grammar become somewhat less clear and you'll have to do the heavy lifting in the custom scope provider but it's really not that difficult to get it to work.


Re: Grammar & Scoping Pattern for variables, functions [message #758270 is a reply to message #739369] Tue, 22 November 2011 09:13 Go to previous messageGo to next message
Zeeshan Safder is currently offline Zeeshan Safder
Messages: 27
Registered: November 2011
Junior Member
hi Matt Campbell

I have to do the similar task. For learing purpose I have pasted your code and tried to execute the grammer. But a function ScopeFor() is missing and I have no idea how to implement it. If you can, can you give that function?

Will be very thankful to you...

Regards
Zeeshan Safder
Re: Grammar & Scoping Pattern for variables, functions [message #758275 is a reply to message #758270] Tue, 22 November 2011 09:28 Go to previous message
Christian Dietrich is currently online Christian Dietrich
Messages: 6198
Registered: July 2009
Senior Member
see org.eclipse.xtext.scoping.Scopes
Previous Topic:firstChild attribute.
Next Topic:Crossreference to member of aliased container
Goto Forum:
  


Current Time: Thu Aug 21 04:34:05 EDT 2014

Powered by FUDForum. Page generated in 0.05857 seconds