首页 > 解决方案 > 引用实例或文字值的 Xtext 语法

问题描述

我正在尝试对基于 XML 的宏进行建模

<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>

稍后将实例化此宏:

<dummy elemName="elem0" elemValue=3 />

但在我可以为宏建模之前,我尝试为元素属性分配一个值(字符串/整数)或参数引用

这是我目前掌握的 Xtext 语法

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*) ;

上述语法只允许引用现有参数。如何直接为元素赋值?

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'.

编辑 1:基于Xtext 语法变量定义/引用中的示例,我修改了我的语法:

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;

但是生成器失败了

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)

编辑 2:语法适用于整数

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*) ;

以下代码有效

IntParameter dummy { value 4 }

Element { name dummy }
Element { name 5 }

任何想法它如何适用于字符串?

标签: eclipsextexteclipse-emf

解决方案


通过改变StringValue

StringValue:
    ref=[StringParameter|EString] | value=EString

StringValue:
    ref=[StringParameter] | value=EString

为我工作。语法现在看起来像:

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;

代码是

StringParameter test { value hello }

Element { name "world" }
Element { name test }

推荐阅读