引用实例或文字值的 Xtext 语法

Posted

技术标签:

【中文标题】引用实例或文字值的 Xtext 语法【英文标题】:Xtext grammar with either reference to instance or literal value 【发布时间】:2021-12-12 22:36:43 【问题描述】:

我正在尝试为基于 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 variable definition/reference中的例子,我修改了我的语法:

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 

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

【问题讨论】:

【参考方案1】:

通过将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 

【讨论】:

以上是关于引用实例或文字值的 Xtext 语法的主要内容,如果未能解决你的问题,请参考以下文章

markDown基本语法

Xtext 和 ANTLR 之间的关系是啥?

markdown基础语法整理

Markdown 语法 示例 字体 字号 颜色

Markdown 语法 示例 字体 字号 颜色

Markdown基础语法