Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » designing grammar for correct scoping context
designing grammar for correct scoping context [message #775163] Thu, 05 January 2012 13:31 Go to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hello,

Are there some grammar rules documented, which should be followed to know what kind of context will be obtained by scoping? In the grammar I am working on, I use simple actions an return types like this:

ContextRef returns Reference:
	{ContextRef} 'this' (primaryRef=PrimaryRef | rangeRef=RangeRef);

PrimaryRef returns Reference:
	(components+=OperatorRef)+ ('->' leafRef=LeafReference)?;

ResourceRef returns LeafReference:
	{ResourceRef} 'RESOURCE' (resource=[library::BaseResource | FQN] | all?='ALL') rangeRef=RangeRef;


with declarative scoping, I would like to reduce the visible set of x-references in the rule "ResourceRef" example, however I find my scope is not "ResourceRef" (as I would expect), but in my case the root type of the grammar . I guess ResourceRef is not created yet, but what are the rules of thumb to know which context to expect in the scope or how do I define the grammar so that ResourceRef is the context ( I would even be happy if the ContextRef rule was the context)?

It sounds like I am asking, how the lazy creation works in relation to Actions in the grammar?.

thank you, Christophe

Full grammar below here....

/*******************************************************************************
NetXScript interpreter. 
Supports: 

Arithmetics
Functions
Variables
Keyword substitution, and referenced model/feature lookup.

*******************************************************************************/
grammar com.netxforge.Netxscript with org.eclipse.xtext.common.Terminals

generate netxscript "http://www.netxforge.com/Netxscript"

// Declare an alias to access ecore types. 
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
// Note we can't use the nsURI, as it won't be found in development time. On the other hand the resource
// uri won't be found in runtime??? 
//import "platform:/resource/com.netxforge.model.a/model/library.ecore" as library
import "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/library.ecore" as library
import "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/operators.ecore" as operator
import "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/metrics.ecore" as metric

Mod:
	('mod' name=ID)?
	(imports+=Import)*
	((functions+=Function)+ |
	(statements+=Statement)+);

Import:
	'import' importURI=STRING;

Function:
	'def' name=ID '(' (args+=Argument (',' args+=Argument)*)? ')' block=Block;

Argument:
	name=ID ;

AbstractVarOrArgument:
	VariableStatement | Argument;

AbstractFunction:
	Function;

Block:
	{Block} '{' statements+=Statement* '}';

Statement:
	(VariableStatement | AssignmentStatement | PlusAssignmentStatement | ReferenceAssignmentStatement | expression=Expression | ReturnStatement) ';'
	| IfStatement | WhileStatement | Block;

ReturnStatement returns Statement:
	{Return} 'return' (expression=Expression)?;

IfStatement returns Statement:
	{If} 'if' '(' if=Logical ')' then=Block ('else' else=Block)?;

WhileStatement returns Statement:
	{While} 'while' '(' predicate=Logical ')' body=Block;

VariableStatement returns Statement:
	{Variable} 'var' name=ID (('=') expression=Expression)?;

AssignmentStatement returns Statement:
	{Assignment} var=[AbstractVarOrArgument]  '='  expression=Expression;

PlusAssignmentStatement returns Statement:
	{PlusAssignment} var=[AbstractVarOrArgument]  '+='  expression=Expression;

//AssignmentStatement returns Statement:
//	VarOrArgumentCall ({IndexedAssignment.assignment=current})?  '=' expression=Expression;

ReferenceAssignmentStatement returns Statement:
	{RefAssignment} assignmentRef=(ContextRef | NodeTypeRef ) '=' expression=Expression;

// Expression, all operators extend this class. 
Expression:
	Logical;

	// Logical	
Logical returns Expression:
	Equality (({And.left=current} '&&' | {Or.left=current} '||') right=Equality)*;

	// Equal, Non-Equal 
Equality returns Expression:
	Comparison (({Equal.left=current} '==' | {Unequal.left=current} '!=') right=Comparison)*;

	// Lesser, Greater. 
Comparison returns Expression:
	Addition (({Lesser.left=current} '<' | {LesserEqual.left=current} '<=' | {Greater.left=current} '>' |
	{GreaterEqual.left=current} '>=') right=Addition)*;

Addition returns Expression:
	Multiplication (({Plus.left=current} '+' | {Minus.left=current} '-') right=Multiplication)*;

Multiplication returns Expression:
	Unary (({Multi.left=current} '*' | {Div.left=current} '/' | {Modulo.left=current} '%') right=Unary)*;

	// Unaries are return type specific. The type on the right should be checked.  
Unary returns Expression:
	PrimaryExpression | ({Negation} op='!' | {UnaryPlusMinus} op=UnaryOperator) right=Unary;

UnaryOperator:
	'-' | '+';

// The FunctionCall and potential parameters, shoul be checked as reference priot to a regular Assignment call. 
PrimaryExpression returns Expression:
	Literal | Range | NativeExpression | Reference | FunctionCall | IndexedCall | ParenthesizedExpression;


Literal returns Expression:
	 NumberLiteral | {BooleanLiteral} (condition?='true' | 'false');

NumberLiteral returns Expression:
	{NumberLiteral} value=NUMBER
;

ParenthesizedExpression returns Expression:
	'(' Expression ')';

FunctionCall returns Expression:
	{FunctionCall} func=[AbstractFunction] '(' (args+=Expression (',' args+=Expression)*)? ')';

IndexedCall returns Expression:
	VarOrArgumentCall ('[' index=Expression ']')?
;

NativeExpression returns Expression:
	{NativeExpression} (range=RangeLiteral | ref=Reference | var=VarOrArgumentCall) '.' nativeFunction=NativeFunction;


VarOrArgumentCall returns Expression:
	{VarOrArgumentCall} call=[AbstractVarOrArgument];

Range:
	RangeLiteral;

RangeLiteral returns Range:
	{RangeLiteral} '[' (values+=NUMBER (',' values+=NUMBER)*)? ']';

enum NativeFunction:
	COUNT='count()' | SUM='sum()' | MIN='min()' | MAX='max()' | MEAN='mean()' | DEVIATION='deviation()' | ERLANGB='erlangB()' | CLEAR ='clear()';

Reference returns Expression:
	ContextRef | NodeTypeRef | NodeRef | ParamRef
;

ParamRef returns Reference:
	{ParamRef} 'PARAM' param=[library::Parameter | FQN]
;

/**
 * The Node context can be found with NODE if available.
 */
NodeTypeRef returns Reference:
	{NodeTypeRef} 'NETYPE' nodetype=[library::NodeType] primaryRef=PrimaryRef
;

NodeRef returns Reference:
	{NodeRef} 'NE' node=[operator::Node] primaryRef=PrimaryRef
;

/**
 * Contextual reference will be restricted by a container in the scope provider
 * depending on the object representation of 'this', until implemented, all possible 
 * references will be visible.  
 */

ContextRef returns Reference:
	{ContextRef} 'this' (primaryRef=PrimaryRef | rangeRef=RangeRef);

/**
 * Exteral Node references, these can be nested and finish with a resource reference.
 */
 
PrimaryRef returns Reference:
	(components+=OperatorRef)+ ('->' leafRef=LeafReference)?;

OperatorRef returns Reference:
	{OperatorRef} '.' ( 'FUNCTION' function=[library::Function | FQN] | 'EQUIPMENT' equipment=[library::Equipment | FQN] | 'PROFILE' | 'STATUS')
;

LeafReference returns LeafReference:
	ResourceRef | LinkRef | StatusRef;

ResourceRef returns LeafReference:
	{ResourceRef} 'RESOURCE' (resource=[library::BaseResource | FQN] | all?='ALL') rangeRef=RangeRef;

StatusRef returns LeafReference:
	{StatusRef} tolerancelevel=ToleranceLevel;

/**
 * Optional value kind AVG / BH
 * Optional Number value (In minutes like 60, etc..)
 * 
 */
RangeRef:
	valuerange=ValueRange (kind=ValueKind)? (interval = Interval)?
;

Interval: 
	interval=NUMBER | kind=IntervalKind
	; 

enum IntervalKind:
	MONTH="MONTH" | WEEK="WEEK" |  DAY="DAY" | HOUR="HOUR"   
;

enum ToleranceLevel:
	RED='RED' | AMBER='AMBER' | GREEN='GREEN' | YELLOW='YELLOW'
;


enum ValueRange: 
	METRIC='METRIC' | CAP='CAP' | FORECAST='FORECAST' | FORECAST_CAP='FORECAST_CAP' | TRENDED='TRENDED' | UTILIZATION='UTILIZATION'	| TOLERANCE='TOLERANCE' | DERIVED="DERIVED"
;

enum ValueKind: 
	AVG='AVG' | BH='BH'
;


/**
 * TODO, through a link, we should be able to access, the opposite node and 
 * resources. 
 * 
 */
LinkRef returns LeafReference:
	{LinkRef} 'LINK' link=[operator::Relationship]
;

FQN :
	SPACED_ID ('::' SPACED_ID)*
;

SPACED_ID returns ecore::EString:
	(ID | NUMBER) (ID | NUMBER )*
;  


terminal NUMBER returns ecore::EBigDecimal:
	('0'..'9')* ('.' ('0'..'9')+)?;

terminal INT returns ecore::EInt:
	'zzzzzzzzz';
	
/*
 * - Can have quotes and dash. 
 */
terminal ID : '^'?('a'..'z'|'A'..'Z'|'_'|'-'|'('| ')') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'-'|'('| ')')*;
	
	
Re: designing grammar for correct scoping context [message #775174 is a reply to message #775163] Thu, 05 January 2012 13:57 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Christophe,

please provide some more information about your scope provider.
How does your method signature look like and how is it called?

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 05.01.12 14:31, schrieb Christophe Bouhier:
> Hello,
> Are there some grammar rules documented, which should be followed to
> know what kind of context will be obtained by scoping? In the grammar I
> am working on, I use simple actions an return types like this:
>
> ContextRef returns Reference:
> {ContextRef} 'this' (primaryRef=PrimaryRef | rangeRef=RangeRef);
>
> PrimaryRef returns Reference:
> (components+=OperatorRef)+ ('->' leafRef=LeafReference)?;
>
> ResourceRef returns LeafReference:
> {ResourceRef} 'RESOURCE' (resource=[library::BaseResource | FQN] |
> all?='ALL') rangeRef=RangeRef;
>
>
> with declarative scoping, I would like to reduce the visible set of
> x-references in the rule "ResourceRef" example, however I find my scope
> is not "ResourceRef" (as I would expect), but in my case the root type
> of the grammar . I guess ResourceRef is not created yet, but what are
> the rules of thumb to know which context to expect in the scope or how
> do I define the grammar so that ResourceRef is the context ( I would
> even be happy if the ContextRef rule was the context)?
> It sounds like I am asking, how the lazy creation works in relation to
> Actions in the grammar?.
> thank you, Christophe
>
> Full grammar below here....
>
>
> /*******************************************************************************
>
> NetXScript interpreter. Supports:
> Arithmetics
> Functions
> Variables
> Keyword substitution, and referenced model/feature lookup.
>
> *******************************************************************************/
>
> grammar com.netxforge.Netxscript with org.eclipse.xtext.common.Terminals
>
> generate netxscript "http://www.netxforge.com/Netxscript"
>
> // Declare an alias to access ecore types. import
> "http://www.eclipse.org/emf/2002/Ecore" as ecore
> // Note we can't use the nsURI, as it won't be found in development
> time. On the other hand the resource
> // uri won't be found in runtime??? //import
> "platform:/resource/com.netxforge.model.a/model/library.ecore" as library
> import
> "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/library.ecore"
> as library
> import
> "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/operators.ecore"
> as operator
> import
> "platform:/resource/com.netxforge.netxstudio.models/models/cdo/13042011/metrics.ecore"
> as metric
>
> Mod:
> ('mod' name=ID)?
> (imports+=Import)*
> ((functions+=Function)+ |
> (statements+=Statement)+);
>
> Import:
> 'import' importURI=STRING;
>
> Function:
> 'def' name=ID '(' (args+=Argument (',' args+=Argument)*)? ')' block=Block;
>
> Argument:
> name=ID ;
>
> AbstractVarOrArgument:
> VariableStatement | Argument;
>
> AbstractFunction:
> Function;
>
> Block:
> {Block} '{' statements+=Statement* '}';
>
> Statement:
> (VariableStatement | AssignmentStatement | PlusAssignmentStatement |
> ReferenceAssignmentStatement | expression=Expression | ReturnStatement) ';'
> | IfStatement | WhileStatement | Block;
>
> ReturnStatement returns Statement:
> {Return} 'return' (expression=Expression)?;
>
> IfStatement returns Statement:
> {If} 'if' '(' if=Logical ')' then=Block ('else' else=Block)?;
>
> WhileStatement returns Statement:
> {While} 'while' '(' predicate=Logical ')' body=Block;
>
> VariableStatement returns Statement:
> {Variable} 'var' name=ID (('=') expression=Expression)?;
>
> AssignmentStatement returns Statement:
> {Assignment} var=[AbstractVarOrArgument] '=' expression=Expression;
>
> PlusAssignmentStatement returns Statement:
> {PlusAssignment} var=[AbstractVarOrArgument] '+=' expression=Expression;
>
> //AssignmentStatement returns Statement:
> // VarOrArgumentCall ({IndexedAssignment.assignment=current})? '='
> expression=Expression;
>
> ReferenceAssignmentStatement returns Statement:
> {RefAssignment} assignmentRef=(ContextRef | NodeTypeRef ) '='
> expression=Expression;
>
> // Expression, all operators extend this class. Expression:
> Logical;
>
> // Logical
> Logical returns Expression:
> Equality (({And.left=current} '&&' | {Or.left=current} '||')
> right=Equality)*;
>
> // Equal, Non-Equal Equality returns Expression:
> Comparison (({Equal.left=current} '==' | {Unequal.left=current} '!=')
> right=Comparison)*;
>
> // Lesser, Greater. Comparison returns Expression:
> Addition (({Lesser.left=current} '<' | {LesserEqual.left=current} '<=' |
> {Greater.left=current} '>' |
> {GreaterEqual.left=current} '>=') right=Addition)*;
>
> Addition returns Expression:
> Multiplication (({Plus.left=current} '+' | {Minus.left=current} '-')
> right=Multiplication)*;
>
> Multiplication returns Expression:
> Unary (({Multi.left=current} '*' | {Div.left=current} '/' |
> {Modulo.left=current} '%') right=Unary)*;
>
> // Unaries are return type specific. The type on the right should be
> checked. Unary returns Expression:
> PrimaryExpression | ({Negation} op='!' | {UnaryPlusMinus}
> op=UnaryOperator) right=Unary;
>
> UnaryOperator:
> '-' | '+';
>
> // The FunctionCall and potential parameters, shoul be checked as
> reference priot to a regular Assignment call. PrimaryExpression returns
> Expression:
> Literal | Range | NativeExpression | Reference | FunctionCall |
> IndexedCall | ParenthesizedExpression;
>
>
> Literal returns Expression:
> NumberLiteral | {BooleanLiteral} (condition?='true' | 'false');
>
> NumberLiteral returns Expression:
> {NumberLiteral} value=NUMBER
> ;
>
> ParenthesizedExpression returns Expression:
> '(' Expression ')';
>
> FunctionCall returns Expression:
> {FunctionCall} func=[AbstractFunction] '(' (args+=Expression (','
> args+=Expression)*)? ')';
>
> IndexedCall returns Expression:
> VarOrArgumentCall ('[' index=Expression ']')?
> ;
>
> NativeExpression returns Expression:
> {NativeExpression} (range=RangeLiteral | ref=Reference |
> var=VarOrArgumentCall) '.' nativeFunction=NativeFunction;
>
>
> VarOrArgumentCall returns Expression:
> {VarOrArgumentCall} call=[AbstractVarOrArgument];
>
> Range:
> RangeLiteral;
>
> RangeLiteral returns Range:
> {RangeLiteral} '[' (values+=NUMBER (',' values+=NUMBER)*)? ']';
>
> enum NativeFunction:
> COUNT='count()' | SUM='sum()' | MIN='min()' | MAX='max()' |
> MEAN='mean()' | DEVIATION='deviation()' | ERLANGB='erlangB()' | CLEAR
> ='clear()';
>
> Reference returns Expression:
> ContextRef | NodeTypeRef | NodeRef | ParamRef
> ;
>
> ParamRef returns Reference:
> {ParamRef} 'PARAM' param=[library::Parameter | FQN]
> ;
>
> /**
> * The Node context can be found with NODE if available.
> */
> NodeTypeRef returns Reference:
> {NodeTypeRef} 'NETYPE' nodetype=[library::NodeType] primaryRef=PrimaryRef
> ;
>
> NodeRef returns Reference:
> {NodeRef} 'NE' node=[operator::Node] primaryRef=PrimaryRef
> ;
>
> /**
> * Contextual reference will be restricted by a container in the scope
> provider
> * depending on the object representation of 'this', until implemented,
> all possible * references will be visible. */
>
> ContextRef returns Reference:
> {ContextRef} 'this' (primaryRef=PrimaryRef | rangeRef=RangeRef);
>
> /**
> * Exteral Node references, these can be nested and finish with a
> resource reference.
> */
>
> PrimaryRef returns Reference:
> (components+=OperatorRef)+ ('->' leafRef=LeafReference)?;
>
> OperatorRef returns Reference:
> {OperatorRef} '.' ( 'FUNCTION' function=[library::Function | FQN] |
> 'EQUIPMENT' equipment=[library::Equipment | FQN] | 'PROFILE' | 'STATUS')
> ;
>
> LeafReference returns LeafReference:
> ResourceRef | LinkRef | StatusRef;
>
> ResourceRef returns LeafReference:
> {ResourceRef} 'RESOURCE' (resource=[library::BaseResource | FQN] |
> all?='ALL') rangeRef=RangeRef;
>
> StatusRef returns LeafReference:
> {StatusRef} tolerancelevel=ToleranceLevel;
>
> /**
> * Optional value kind AVG / BH
> * Optional Number value (In minutes like 60, etc..)
> * */
> RangeRef:
> valuerange=ValueRange (kind=ValueKind)? (interval = Interval)?
> ;
>
> Interval: interval=NUMBER | kind=IntervalKind
> ;
> enum IntervalKind:
> MONTH="MONTH" | WEEK="WEEK" | DAY="DAY" | HOUR="HOUR" ;
>
> enum ToleranceLevel:
> RED='RED' | AMBER='AMBER' | GREEN='GREEN' | YELLOW='YELLOW'
> ;
>
>
> enum ValueRange: METRIC='METRIC' | CAP='CAP' | FORECAST='FORECAST' |
> FORECAST_CAP='FORECAST_CAP' | TRENDED='TRENDED' |
> UTILIZATION='UTILIZATION' | TOLERANCE='TOLERANCE' | DERIVED="DERIVED"
> ;
>
> enum ValueKind: AVG='AVG' | BH='BH'
> ;
>
>
> /**
> * TODO, through a link, we should be able to access, the opposite node
> and * resources. * */
> LinkRef returns LeafReference:
> {LinkRef} 'LINK' link=[operator::Relationship]
> ;
>
> FQN :
> SPACED_ID ('::' SPACED_ID)*
> ;
>
> SPACED_ID returns ecore::EString:
> (ID | NUMBER) (ID | NUMBER )*
> ;
>
> terminal NUMBER returns ecore::EBigDecimal:
> ('0'..'9')* ('.' ('0'..'9')+)?;
>
> terminal INT returns ecore::EInt:
> 'zzzzzzzzz';
>
> /*
> * - Can have quotes and dash. */
> terminal ID : '^'?('a'..'z'|'A'..'Z'|'_'|'-'|'('| ')')
> ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'-'|'('| ')')*;
>
>
>
Re: designing grammar for correct scoping context [message #775181 is a reply to message #775174] Thu, 05 January 2012 14:12 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
W.r.t. the actions: seems to me that the ContextRef and ResourceRef simple actions are not necessary since there will always be an assignment. Apart from that, I wouldn't expect this to alter the situation.

For some generic tips w.r.t. scoping providers: http://dslmeinte.wordpress.com/2010/09/06/tricks-for-implementing-scoping/ - written for Xtext1.0.1 but still valid for Xtext2.x.y, I think.


Re: designing grammar for correct scoping context [message #775195 is a reply to message #775174] Thu, 05 January 2012 14:39 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi Sebastian,

this is the method sign. in my "NetxscriptScopeProvider"

IScope scope_ResourceRef_resource(final EObject context, EReference reference){
// context is of instance Mod, see the full grammar.

System.out.println("SCOPING: custom scoping called for scope_ResourceRef_resource" );
return null;
}

it get's called all right, but not with the context I expect.

It's called by the polymorphicdispatcher in the abstract super. (Do you mean where exactly it's called?).

rgds Christophe
Re: designing grammar for correct scoping context [message #775202 is a reply to message #775181] Thu, 05 January 2012 14:52 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi Meinte,

thank you for responding. As I want ie. ResourceRef to extend LeafReference, I tell it to return LeafReference
and add the simple action so ResourceRef get's instantiated. What I understood, this is the way to achieve inheritance. Did I miss something?

I read your blog now and then, love your stuff. thanks for this.
rgds Christophe
Re: designing grammar for correct scoping context [message #775210 is a reply to message #775202] Thu, 05 January 2012 15:12 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
Ah, didn't see the returns-clauses there. It's one way to achieve inheritance, for sure.

Re: designing grammar for correct scoping context [message #775214 is a reply to message #775195] Thu, 05 January 2012 15:13 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Christophe,

how often is your method called per reference? I'd expect that it is
used with the ResourceRef as the context, too.

How does the input file look like?

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 05.01.12 15:39, schrieb Christophe Bouhier:
> Hi Sebastian,
> this is the method sign. in my "NetxscriptScopeProvider"
>
> IScope scope_ResourceRef_resource(final EObject context, EReference
> reference){
> // context is of instance Mod, see the full grammar.
> System.out.println("SCOPING: custom scoping called for
> scope_ResourceRef_resource" );
> return null;
> }
>
> it get's called all right, but not with the context I expect.
> It's called by the polymorphicdispatcher in the abstract super. (Do you
> mean where exactly it's called?).
> rgds Christophe
Re: designing grammar for correct scoping context [message #775229 is a reply to message #775214] Thu, 05 January 2012 15:46 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi,

For a valid statement with the following input:

this. FUNCTION SW Licenses -> RESOURCE STP_ORIGMSUS CAP;


...it's called several times.

SCOPING: custom scoping called for scope_ResourceRef_resource with context type=ResourceRef
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=Reference
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=ContextRef
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=Statement
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=Mod


but when the content assist is invoked here: it's only called once. ('|' is the cursor position).

this. FUNCTION SW Licenses -> RESOURCE |



It kind of makes sense, as I have this inheritance structure, which prevents it from creating the object, but
this is exactly what I would like to understand better. Is inheritance preventing ResourceRef to be created until
a fully valid Statement is available (line ending with ';') ?

Can I keep the inheritance and still have the super objects created somehow?
thx Christophe


Re: designing grammar for correct scoping context [message #775242 is a reply to message #775229] Thu, 05 January 2012 16:11 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Christophe,

content assist has to deal with incomplete models. The parser may decide
to choose another path than you'd expect, e.g. even though the keyword
RESOURCE is present, it may use another alternative especially if you
have backtracking enabled in your grammar. If no instance of ResourceRef
is available, non can be passed to the scope provider. Therefore it'll
use a container that may use a possible to-be-created ResourceRef as its
transitive content. Thus the behavior that you observed. Do you have
backtracking enabled?

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 05.01.12 16:46, schrieb Christophe Bouhier:
> Hi,
> For a valid statement with the following input:
> this. FUNCTION SW Licenses -> RESOURCE STP_ORIGMSUS CAP;
>
> ...it's called several times.
> SCOPING: custom scoping called for scope_ResourceRef_resource with
> context type=ResourceRef
> SCOPING: custom scoping called for scope_ResourceRef_resource with
> context type=Reference
> SCOPING: custom scoping called for scope_ResourceRef_resource with
> context type=ContextRef
> SCOPING: custom scoping called for scope_ResourceRef_resource with
> context type=Statement
> SCOPING: custom scoping called for scope_ResourceRef_resource with
> context type=Mod
>
>
> but when the content assist is invoked here: it's only called once. ('|'
> is the cursor position).
> this. FUNCTION SW Licenses -> RESOURCE |
>
>
> It kind of makes sense, as I have this inheritance structure, which
> prevents it from creating the object, but this is exactly what I would
> like to understand better. Is inheritance preventing ResourceRef to be
> created until a fully valid Statement is available (line ending with ';') ?
> Can I keep the inheritance and still have the super objects created
> somehow? thx Christophe
>
>
>
Re: designing grammar for correct scoping context [message #775251 is a reply to message #775242] Thu, 05 January 2012 16:35 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi Sebastian,
Thanks for your help sofar. As for backtracking it's disabled I believe consider this .MWE2 snippet:

            // The antlr parser generator fragment.
            fragment = parser.antlr.XtextAntlrGeneratorFragment {
            //  options = {
            //      backtrack = true
            //  }
            }


Not sure what you mean with: "transitive content."?
So even, with backtracking disabled, is there a way I can solve this issue? Would it mean re-designing the grammar with less inheritance? (I keep coming back to this, intuitively it feels as the root of the problem).
Re: designing grammar for correct scoping context [message #775271 is a reply to message #775251] Thu, 05 January 2012 17:23 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Christophe,

inheritance is unlikely the cause for the problem. I'm pretty sure it's
the error recovery mechanism of the generated parser that's causing your
headache.
If you drill down into your Mod in the debugger, do you find a
ResourceRef instance there in the content assist scenario?

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 05.01.12 17:35, schrieb Christophe Bouhier:
> Hi Sebastian, Thanks for your help sofar. As for backtracking it's
> disabled I believe consider this .MWE2 snippet:
>
> // The antlr parser generator fragment.
> fragment = parser.antlr.XtextAntlrGeneratorFragment {
> // options = {
> // backtrack = true
> // }
> }
>
>
> Not sure what you mean with: "transitive content."?
> So even, with backtracking disabled, is there a way I can solve this
> issue? Would it mean re-designing the grammar with less inheritance? (I
> keep coming back to this, intuitively it feels as the root of the problem).
Re: designing grammar for correct scoping context [message #775601 is a reply to message #775271] Fri, 06 January 2012 10:40 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi Sebastian,

Nope the Mod is empty at that point in time, BUT I re-thought the whole grammar, and decided that it didn't make sense to have an Expression as a Statement which would not be part of the left or right side of an assignment. So changing this:

Statement:
	(VariableStatement | AssignmentStatement | PlusAssignmentStatement | ReferenceAssignmentStatement | expression=Expression | ReturnStatement) ';'
	| IfStatement | WhileStatement | Block;


into this: (remove option "Expression" from this rule.

Statement:
	(VariableStatement | AssignmentStatement | PlusAssignmentStatement | ReferenceAssignmentStatement | ReturnStatement) ';'
	| IfStatement | WhileStatement | Block;


yields the following context result for:

this. FUNCTION SW Licenses -> RESOURCE |



SCOPING: custom scoping called for scope_ResourceRef_resource with context type=ResourceRef
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=Reference
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=ContextRef
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=RefAssignment
SCOPING: custom scoping called for scope_ResourceRef_resource with context type=Mod


So these are the context calls I need, it's now clear which path the parser takes, it anticipates a RefAssignment.
However, the downside of this solution is that If I want to write an expression, I always have to write the left side first as the parser will anticipate an assignment first and content proposal will only show assignments rules (Instead of all other expression operators).

Is this a known pattern? Could I still go back to my original grammar and put some syntactic predicates to "steer" the parser some how?

Thanks for your help!
Re: designing grammar for correct scoping context [message #775644 is a reply to message #775601] Fri, 06 January 2012 12:51 Go to previous message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
The scoping debug info shows that scoping is evaluated through the parent structure of the "lowest" context, corresponding to the path the parser happens to take. It is possible to influence that path, so some extent (Xtext's syntactic predicates are a more restricted version of the ones known from ANTLR/yacc etc.); see e.g.: http://dslmeinte.wordpress.com/2011/12/20/using-syntactic-predicates-in-xtext-part-2/ http://dslmeinte.wordpress.com/2011/12/05/using-syntactic-predicates-in-xtext-part-1/

Previous Topic:Serialization format
Next Topic:ResourceDescriptionsProvider
Goto Forum:
  


Current Time: Sat Apr 27 05:01:28 GMT 2024

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

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

Back to the top