Home » Modeling » TMF (Xtext) » About cross references & scoping
About cross references & scoping [message #1005813] |
Mon, 28 January 2013 20:15 |
thomas klutsch Messages: 1 Registered: January 2013 |
Junior Member |
|
|
Hi there!
I just signed up here as a person that is by now totally desperate! I've searched what felt like the entire internet for answers to what I think is a quite a simple question about xtext, but have yet to succeed. This is my last hope to find an answer
So what is it about: It's about cross references and scoping in xtext.
Okay so in my grammar, there are some cross-references, like:
SomeRule:
name = [SomeOtherRule];
But this doesn't always work in the generated language. It works in most cases, but sometimes, I get messages "couldn't resolve reference to SomeOtherRule x".
I've read everything what is written about scoping in the Xtext documentation. Maybe I'm just plain stupid, but that didn't help me AT ALL, as it just comes up with all kinds of different interfaces and classes and buzzwords, but it does not explain how the default scoping behaviour actually works in practice.
Aside from that I found a few blog entries where people have written stuff about the scoping. But that didn't help me either.
So then I tried to experiment with little self-created grammar examples to find out when exactly a cross-references works and when not. But I just don't get the rules behind the mechanism. For me it's just magic.
I spend hours to try to come up with an example, but because I don't understand it yet, I fail to do so. The only thing I can do is give you my entire concrete grammer where the problem occurs - without me understanding it. This is quite some code, and surely some things may not be relevant to the example I'll give you. But I don't know which are and which are not, and if it would change something semantically if I try to simplify it. So, don't get a heart attack, you won't need to think through all of this, but for the sake of completeness, I'll post everything
(by the way this grammar tries to implement the QVT Relations Language)
TopLevel:
(transformations+=Transformation)*;
Transformation:
'transformation' name=ID
'('
modelDeclarations+=ModelDeclaration (',' modelDeclarations+=ModelDeclaration)*
')'
('extends' superTransformation=[Transformation])?
'{'
(keyDeclarations+=KeyDeclaration)*
(relations+=Relation | functions+=Function)*
'}';
ModelDeclaration:
name=ID ':'
metaModelIds+=MetaModelId
|
('{' metaModelIds+=MetaModelId (',' metaModelIds+=MetaModelId)* '}');
MetaModelId:
name=ID;
KeyDeclaration:
'key' classId=ClassId
'{'
keyProperties+=KeyProperty (',' keyProperties+=KeyProperty)*
'}'
';';
ClassId:
name=ID;
KeyProperty:
PrimitiveKeyProperty | OppositeKeyProperty;
PrimitiveKeyProperty:
name=ID;
OppositeKeyProperty:
'opposite'
'('
classId=ClassId '.' name=ID
')';
Relation:
('top')? 'relation' name=ID
('overrides' superRelation=[Relation])?
'{'
(variableDeclarations+=VariableDeclaration)*
(domains+=Domain)+
(whenStatement=WhenStatement)?
(whereStatement=WhereStatement)?
'}';
VariableDeclaration:
name+=VariableName (',' name+=VariableName)* ':' type=TypeCS ';';
VariableName:
name=ID;
TypeCS:
name=ID;
Domain:
PrimitiveTypeDomain | ComplexDomain;
PrimitiveTypeDomain:
'primitive' 'domain' name=VariableName ':' type=TypeCS ';';
ComplexDomain:
('checkonly' | 'enforce')? 'domain'
modelId=[ModelDeclaration]
template=Template
('default_values' '{' (assignmentExpressions+=AssignmentExpression)+ '}')?
';';
AssignmentExpression:
name=ID '=' oclExpression=OclExpressionCS ';';
Template:
(name=VariableName)? ':' classId=ClassId
'{'
(propertyTemplateList=PropertyTemplateList)?
'}'
('{' oclExpression=OclExpressionCS '}')?;
PropertyTemplateList:
propertyTemplates+=PropertyTemplate (',' propertyTemplates+=PropertyTemplate)*;
PropertyTemplate:
PrimitivePropertyTemplate | OppositePropertyTemplate;
PrimitivePropertyTemplate:
name=ID '=' oclExpression=OclExpressionCS;
OppositePropertyTemplate:
'opposite'
'('
classId=ClassId '.' name=ID
')'
'=' oclExpression=OclExpressionCS;
WhenStatement:
{WhenStatement}
'when'
'{'
(oclExpressions+=OclExpressionCS ';')*
'}';
WhereStatement:
{WhereStatement}
'where'
'{'
(oclExpressions+=OclExpressionCS ';')*
'}';
Function:
'function' name=ID
'('
(parameters+=ParameterDeclaration (',' parameters+=ParameterDeclaration)*)?
')'
':' type=TypeCS
(';' | '{' oclExpression=OclExpressionCS '}');
ParameterDeclaration:
name=VariableName ':' type=TypeCS;
OclExpressionCS:
concatenatedOclExpressions+=ConcatenatedOclExpression
('=' concatenatedOclExpressions+=ConcatenatedOclExpression)?;
ConcatenatedOclExpression:
oclExpressionTerms+=OclExpressionTerm ('+' oclExpressionTerms+=OclExpressionTerm)*;
OclExpressionTerm:
'(' OclExpressionCS ')' | Template | IfExpCS | VariableExpCS | CallExpCS | LiteralExpCS;
IfExpCS:
'if' ifOclExpression=OclExpressionCS
'then' thenOclExpression=OclExpressionCS
'else' elseOclExpression=OclExpressionCS
'endif';
VariableExpCS:
name=[VariableName];
CallExpCS:
PropertyCallExpCS | CodeCallExp;
PropertyCallExpCS:
name=[VariableName] '.' properties+=Property ('.' properties+=Property)*;
Property:
name=ID;
CodeCallExp:
name=[CallableCode]
'('
(parameters+=CodeCallExpParameter)? (',' parameters+=CodeCallExpParameter)*
')';
CallableCode:
Relation | Function;
CodeCallExpParameter:
name=[VariableName];
LiteralExpCS:
StringLiteralExp | IntLiteralExp | FloatLiteralExp;
StringLiteralExp:
name=STRING;
IntLiteralExp:
name=INT;
FloatLiteralExp:
name=FLOAT;
terminal FLOAT returns ecore::EFloat:
('0'..'9')+ '.' ('0'..'9')+;
Ok still there? So, now here's a snippet of some example code where a problem with the scope arises:
transformation <...> {
<...>
top relation ClassToTable {
cn, prefix:String;
checkonly domain uml c:Class {
namespace = p:Package {},
kind = 'Persistent',
name = cn
};
enforce domain rdbms t:Table {
schema = s:Schema {},
name = cn,
column = cl:Column {
name = cn + '_tid',
type = 'NUMBER'
},
theKey = k:Key {
name = cn + '_pk',
column = cl ####### ERROR ########
}
};
when {
PackageToSchema (p, s); ####### ERROR ########
}
where {
prefix = '';
AttributeToColumn (c, t, prefix); ####### OKAY #######
}
}
<...>
}
I get errors "couldn't resolve reference to VariableName <x>" at the lines marked with ####### ERROR ########. So the VariableNames p, s and cl are not visible at those points.
However, it seems there's no problem with the variables c, t and prefix (See line marked with ####### OKAY ####### )
And THAT'S what I don't get. Whatever mechanism I think of that xtext might be using, these two incidents seem to be contradictory. Because regarding the hierarchy of the rule's relations, I don't really see a difference?!
...Puh, thanks so much for those of you who have read up to here! I would be so thankful if anyone can explain to me why exactly the references to c, t, and prefix are visible in the where-block, but the references to p and s in the when-block are not.
In one sentence, what I need to understand ist:
What is the default scope of a feature? where can it be references, where not?
Thanks again, Regards Thomas
|
|
|
Re: About cross references & scoping [message #1005862 is a reply to message #1005813] |
Tue, 29 January 2013 06:12 |
|
Hi,
without having a look at your code
(1) xtext by default builds QualifiedNames <ancestorname>.....<Parentname>.<name>
(2) these names are automatically resolved in the context of their relation
(3) xxxx=[YYYY] is short for xxxx=[YYYY|ID]
so a . is not allowed in the reference
(4)you can overcome this by:
(a) giving the things simple names (IQualifiedNameProvider)
(b) allow qualified names in the rule
xxxx=[YYYY|FQN].... FQN: ID ("." ID)*;
you can use crtl+shift+F3 to see the names of your things
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
| |
Goto Forum:
Current Time: Thu Apr 25 17:45:28 GMT 2024
Powered by FUDForum. Page generated in 0.03010 seconds
|