Reputation: 23
I have the following grammar:
Model: prog+=Program*;
Program: g=Greeting de+=DataEntry* s+=Statement*;
Greeting: 'Hello' t=ProgPara '!';
ProgPara: 'PROGRAM' pname=Progname ';';
Progname : name=ID;
DataEntry: a=INT v=Varname ';';
Varname : name = ID;
Statement: (c=CopyStmt|m=MoveStmt) ';';
CopyStmt: 'COPY' 'TO' qname=[IndexVarname|ID] ;
IndexVarname : (Indexname|Varname);
Indexname : '(' name = ID ')';
MoveStmt: 'MOVE' 'TO' p=[PrVarName|ID];
PrVarName : (Varname|Progname);
But it throws error for:
PrVarName : (Varname|Progname);
So i modified the grammar to have as below:
PrVarName : (v=Varname|Progname);
I updated the Scope provider as below:
override getScope(EObject context, EReference reference) {
if (context instanceof CopyStmt) {
if (reference.featureID == TestDslPackage.COPY_STMT__QNAME) {
val rootElement = EcoreUtil2.getRootContainer(context);
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Indexname);
val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
val candidates = candidates1 + candidates2;
return Scopes.scopeFor(candidates);
}
} else if (context instanceof MoveStmt) {
if (reference.featureID == TestDslPackage.MOVE_STMT__P) {
val rootElement = EcoreUtil2.getRootContainer(context);
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Progname);
val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
val candidates = candidates1 + candidates2;
return Scopes.scopeFor(candidates);
}
}
}
Once the grammar was built and i ran the below test case, it is throwing error in the MOVE statement saying "Couldn't resolve reference to PrVarName 'test1'."
Hello PROGRAM test;!
1 test1;
2 test2;
3 test3;
COPY TO test2;
MOVE TO test1;
Looks like i cannot use Varname in two different cross references. But there is a very valid need for it. How do I achieve this?
Thanks in advance.
Upvotes: 0
Views: 725
Reputation: 11868
PrVarName : p=(Progname|Varname);
is bad cause it changes the type hierarchy. Progname and Varname are no longer subtypes of PrVarName. By reverting the change and introducing a common Named supertype you can resolve this
Model:
prog+=Program*;
Program:
g=Greeting de+=DataEntry* s+=Statement*;
Greeting:
'Hello' t=ProgPara '!';
ProgPara:
'PROGRAM' pname=Progname ';';
DataEntry:
a=INT (v=Varname | in=Indexname) ';';
Statement:
(c=CopyStmt | m=MoveStmt) ';';
CopyStmt:
'COPY' 'TO' qname=[IndexVarname|ID];
MoveStmt:
'MOVE' 'TO' p=[PrVarName|ID];
PrVarName:
Progname | Varname;
IndexVarname:
(Indexname | Varname);
Named:Progname|Indexname|Varname;
Progname:
{Progname} name=ID;
Indexname:
{Indexname}'(' name=ID ')';
Varname:
{Varame}name=ID;
Upvotes: 1