Reputation: 969
I am trying to model an XML based macros
<macro name="dummy" parameters="elemName elemValue">
<element name=${elemName} /> <!--reference to parameter elemName-->
<element name="elem1" />
<anotherElement name="elem2" value=6 />
<anotherElement name="elem3" value=${elemValue} />
</macro>
Later this macro will be instantiated:
<dummy elemName="elem0" elemValue=3 />
But before I can model the macro, I trying assign either a value (string / integer) or reference of parameter to the element attributes
This is the Xtext grammar I have got so far
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.eclipse.org/emf/2003/XMLType" as type
Model:
parameters+=Parameter*
intParameters+=IntParameter*
elements+=Element*
otherElements+=AnotherElement*
;
Parameter returns Parameter:
StringParameter | IntParameter
;
StringParameter returns StringParameter:
{StringParameter}
'StringParameter'
name=EString
'{'
('value' value=EString)?
'}';
IntParameter returns IntParameter:
{IntParameter}
'IntParameter'
name=EString
'{'
('value' value=DECINT)?
'}';
Element returns Element:
'Element'
'{'
'name' name=[StringParameter|EString]
'}';
AnotherElement returns AnotherElement:
'AnotherElement'
'{'
'value' value=[IntParameter|EString]
'}';
EString returns ecore::EString:
STRING | ID;
terminal fragment DIGIT: '0'..'9';
terminal DECINT: '0' | ('1'..'9' DIGIT*) | ('-''0'..'9' DIGIT*) ;
The above grammar allows only for references to existing parameters. How can I assign values directly to the elements?
StringParameter test { value "hello" }
IntParameter dummy { value 4 }
Element { name test } // works
Element { name blah } // ERROR: Couldn't resolve reference to StringParameter 'blah'.
AnotherElement { value dummy } // works
AnotherElement { value 7 } // ERROR: no viable alternative at input '7'
// ERROR: Couldn't resolve reference to IntParameter '7'.
Edit 1: Based on the example in Xtext grammar variable definition/reference, I modified my grammar:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Model:
parameters+=StringParameter*
elements+=Element*;
Element returns Element:
'Element'
'{'
'name' value=StringValue
'}';
StringValue:
StringLiteral | StringRefParameter;
StringRefParameter:
ref=[StringParameter|EString];
StringLiteral:
value=EString;
StringParameter returns StringParameter:
{StringParameter}
'StringParameter'
name=EString
'{'
('value' value=EString)?
'}';
EString returns ecore::EString:
STRING | ID;
But the generator fails
1212 [main] INFO text.xtext.generator.XtextGenerator - Generating common infrastructure
1237 [main] ERROR mf.mwe2.launch.runtime.Mwe2Launcher - Problems running workflow org.xtext.example.mydsl.GenerateMyDsl:
[ERROR]: GeneratorException: (Element: -UNKNOWN-; Reported by: XtextGenerator)
org.eclipse.xtext.util.RuntimeIOException: java.io.FileNotFoundException: /home/user/ws/org.xtext.example.mydsl/../org.xtext.example.mydsl/src-gen/org/xtext/example/mydsl/parser/antlr/internal/InternalMyDslLexer.java (No such file or directory)
Edit 2: The grammar works for integers
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Model:
parameters+=IntParameter*
elements+=Element*
;
Element returns Element:
'Element'
'{'
'name' value=IntValue
'}';
IntValue:
ref=[IntParameter] | value=DECINT
;
IntParameter returns IntParameter:
{IntParameter}
'IntParameter'
name=EString
'{'
('value' value=DECINT)?
'}';
EString returns ecore::EString:
STRING | ID;
terminal fragment DIGIT: '0'..'9';
terminal DECINT: '0' | ('1'..'9' DIGIT*) | ('-''0'..'9' DIGIT*) ;
and the following code is valid
IntParameter dummy { value 4 }
Element { name dummy }
Element { name 5 }
Any ideas how could it work for strings?
Upvotes: 0
Views: 550
Reputation: 969
By changing StringValue
from
StringValue:
ref=[StringParameter|EString] | value=EString
to
StringValue:
ref=[StringParameter] | value=EString
works for me. The grammar now looks like:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Model:
stringParameters+=StringParameter*
elements+=Element*
;
Element returns Element:
'Element'
'{'
'name' value=StringValue
'}';
StringValue:
ref=[StringParameter] | value=EString
;
StringParameter returns StringParameter:
{StringParameter}
'StringParameter'
name=EString
'{'
('value' value=EString)?
'}';
EString returns ecore::EString:
STRING | ID;
And the code is
StringParameter test { value hello }
Element { name "world" }
Element { name test }
Upvotes: 1