我有一个语法,在解析 'if' expr 'then'
时有两种不同的可能性.有一个简单的“赋值”,比如if foo then bar=1; else bar=0;
然后就是我所说的“if_block”代码,它可以包含一个或多个“作业”:
if foo then
{
bar = 1;
if xyz then abc = -1;
}
else
{
bar = 0;
if xyz then
{
abc = 0;
}
}
我正在通过 dangling else 处理嵌套的 if_blocks匹配/不匹配的 block 。
我的( 非常 简化)语法基本上是:
program : if_blocks
if_blocks : if_block | if_block if_blocks
if_block : assignments
assignments : assignment | assignment assignments
assignment : simple_assignment | if_assignment
所以我的困境是一个赋值,然后是一个 if_block。例如:
foo = bar;
if foo then
{
foo = foo + 1;
}
foo = bar;
是一个赋值,在这种情况下,应该简化为 if_block。 if foo then { ... }
本身就是一个 if_block。因此,整个代码是 if_block+if_block(简化为 if_blocks)。但是在 foo = bar;
之后被简化为一个赋值,没有足够的前瞻来知道 if foo then
是另一个赋值(在 foo = bar;
if_block 中)或者如果它是一个单独的 if_block。我已添加
%glr-parser
,这似乎解决了这个问题,但我遇到了解析的多个分支仍然存在的其他情况,我似乎无法协调不同的 S/R 分支。对于这种情况,公认的做法是什么,没有切换到完全不同的扫描仪/解析器(这对我来说学习和重写代码需要做很多工作)或更改语言(我不能这样做)?是否有使用 GLR 或调整语法的简单解决方案(以某种方式定义 %dprec
?)?
最佳答案
经典的悬空-else 问题是通过坚持 来解决的。否则 附上最近的如果 ,这(在概念上)解决了歧义。您需要以某种方式将该想法传达给解析器生成器,以使歧义真正消失。
大多数解析器生成器(包括 YACC 和 Bison)都有某种方式表示,当 token 存在 shift-vs-reduce 冲突时,更喜欢“shift”,它可以用来为 实现这种效果。否则 关键词。我不知道YACC或Bison的成语是什么,但是在语法描述信息中应该很容易找到。
(我使用自己的 GLR 解析器,这样说仍然很有用,因为它以一种简单的方式摆脱了模棱两可的解析)。
关于c - 在不求助于 GLR-Parser 的情况下解决模棱两可的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4326963/