XText语法变量定义/引用

2022-08-15 00:00:00 grammar java xtext ebnf
[any type]Realisation语法规则初始化应该是一个值或对预定义变量的引用。 对于Integer,它看起来与您从Java中知道的类似:

public int i = 3;

为什么以下语法引发异常?

Integer returns ecore::ELong:
  (Plus|Minus)? INT;

IntegerRealisation:
  {Integer} Integer | 
  ref=[Integer];

异常:

Caused by: java.io.IOException: Generated EMF Model incomplete: The context 'IntegerRealisation' is not valid for type 'Integer'
Recommended contexts for type 'Integer': 
Other valid contexts for type 'Integer': .... The context 'IntegerRealisation' is valid for types: Integer, IntegerRealisation

为什么同一错误的第一行和最后一行彼此不一致?

这里出了什么问题?


解决方案

您尝试引用的是整型文字,而不是任何其他整型变量。实施某事。如

public int i = 5; // 5 is a value
public int j = i; // i reference to a predefined variable

您的语法定义应如下所示

VariableDeclaration:
    modifiers+=Modifier* type=Type name=ID ('=' value=VariableValue)? ';';

VariableValue:
    TypedLiteral | VariableReference;

TypedLiteral:
    IntegerLiteral | ...;

IntegerLiteral:
    value=INTVAL;

terminal INTVAL returns ecore::ELong:
    (Plus|Minus)? INT;

VariableReference:
    ref=[VariableDeclaration|QualifiedName];

如您所见,它从定义变量的a规则开始。该变量有一个name属性,这对于后面的参考实现非常重要。实际值分配是可选的(因为我会这样做!)在这一点上,重要的是抽象规则VariableValue,它将对文字(也称为.常量值)或对任何其他变量的引用。

如果要引用任何预定义变量,您将使用其他变量名称,但不是其值。因此,我们还需要VariableReference,它定义我们通过(限定)名称(在管道操作符|之后)引用任何其他变量(在管道操作符之前)。

为确保类型安全,您必须实现yourdsl.validation.YourDslValidator类以检查文本是否与类型兼容,以及引用的变量的类型是否与类型兼容。

编辑:我稍微优化了语法。第一个版本有点不清楚。

回答您的其他问题:

变量值的返回类型是什么?

VariableValue本身是所有可能值的公共(但抽象)返回类型。它类似于java.lang.Numberjava.lang.Integerjava.lang.Double、...

的超类型

这里的问题是单词type本身在这里是不明确的。值的类型将是int(IntegerLiteral extends TypedLiteral extends VariableValue),但AST节点的类型是IntegerLiteralVariableReference

要确定VariableReference的值类型,必须查看引用的VariableDeclaration(((VariableReference)vd1.getValue()).getRef().getValue())的value属性。永远不会有EString值类型!

若要为VariableDeclaration.value属性设置值,您需要IntegerLiteral(最显式的TypeWrital)或VariableReference

相关文章