在解析'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。
我的(非常简化)语法基本上是:
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分支。在没有切换到完全不同的扫描仪/解析器(这对我来说学习和重写代码很多工作)或改变语言(我不能做)的情况下,这种情况的公认惯例是什么?是否有一个简单的解决方案(以某种方式定义%dprec
?)使用GLR或对语法进行调整?
答案 0 :(得分:1)
通过坚持将 else 附加到最近的 if 来解决悬空 - 其他问题,这(概念上)解决了歧义。不知何故,你需要将这个想法传达给解析器生成器,以使歧义真正消失。
大多数解析器生成器(包括YACC和Bison)都有一些方法可以说当一个令牌存在shift-vs-reduce冲突时,更喜欢“shift”,这可以用来为 else 关键字。我不知道YACC或Bison的成语是什么,但在语法描述信息中应该很容易找到。
(我使用自己的GLR解析器,说这个仍然很有用,因为它以简单的方式摆脱了模糊的解析)。