问题
Entry
: temp += (Expression | Declaration | UserType)*
;
Declaration
: Type '*' name=ID ';'
;
Expression
: temp1 = Primary ('*' temp2 += Primary)* ';'
;
Primary
: temp1 = INT
| temp2 = [Declaration]
;
Type
: temp1 = SimpleType
| temp2 = [UserType]
;
SimpleType
: 'int' | 'long'
;
UserType
: 'typedef' name=ID ';'
;
规则Declaration
和Expression
是不明确的,因为两个规则共享完全相同的语法并且出现问题,因为交叉引用[Declaration]
和[UserType]
都是基于终端规则ID
。
因此,为上面的语法生成代码将抛出ANTLR警告:
Decision can match input such as "RULE_ID '*' RULE_ID ';'"
using multiple alternatives: 1, 2
目标
我希望选择能够首先解决交叉引用的规则。
假设如下:
typedef x;
int* x;
int* b;
的AST
x*b
应该看起来像:
x = Entry -> Expression -> Primary (temp1) -> [Declaration] -> Stop!
* = Entry -> Expression -> Primary '*' -> Stop!
b = Entry -> Expression -> Primary (temp2) -> [Declaration] -> Stop!
因此
Entry -> Declaration
不应该考虑,因为
Entry -> Expression -> [Declaration]
已经可以验证交叉引用[Declaration]
。
问题
因为我们在Xtext中没有语义谓词(或者我错了吗?),有没有办法验证交叉引用并基于该验证明确选择该规则?
PS:正如一些人可能已经知道的那样,这个问题源于我试图用Xtext实现的C语言。
答案 0 :(得分:0)
关于当前版本的Xtext,不支持语义谓词。
交叉引用已解析为其终端(在我的情况下为UserRole
和Declaration
到终端ID
)。并且只有在链接过程中才会验证引用,在我的情况下,由于AST已经创建,因此为时已晚。
使用上下文敏感规则决策的唯一可行方法是在语法中实际定义表示语法的抽象规则。在上面的示例中,规则Expression
和Declaration
将被重写为一个。然后在必要的领域进行语义验证,例如使用范围确定的内容辅助。