我试图在 DSL 中扩展表达式语言,但我收到了有关优先级的歧义预测警告。在这种情况下我该如何排序优先级(使用扩展)?
例如我们有一个模块A:
module A
lexical Id = [a-z]+; // for the sake of completeness
syntax Exp
= Id
| left Exp "+" Exp
;
然后是扩展它的模块 B:
module B
extend A;
syntax Exp
= left Exp "*" Exp
;
现在,当我们生成解析器时,我们会收到有关
*
和 +
规则之间可能存在歧义的警告。
第一个解决方案是通过重复原始规则来添加优先级。这导致了这个版本的模块 B:
module B
extend A;
syntax Exp
= left Exp "*" Exp
> left Exp "+" Exp
;
前提是
+
规则必须被准确地复制,字面意义上的,这样才能在两个版本的规则之间引入另一个歧义。这包括可能的标签。所以这不起作用:
module B
extend A;
syntax Exp
= left Exp "*" Exp
> left Exp lhs "+" Exp rhs
;
这有点笨拙,因此也可以选择在优先级声明中使用规则名称。为此,原始规则必须有一个名称。模块A变成这样:
module A
syntax Exp
= Id
| left plus: Exp "+" Exp
;
然后我们可以把它写在模块B中:
module B
extend A;
syntax Exp
= left times:Exp "*" Exp
> :plus // the reference to the other rule in module A
;
简而言之:在任何可以编写完整规则的地方,
>
符号的左侧或右侧,在关联组内等等,您都可以编写:<label>
来引用任何现有的标记规则对于相同的非终结符但可能在不同的规则中,甚至在不同的扩展或导入模块中。如果您不想添加标签,则需要重复整个规则。