在LALR(1)语法分析器中,语法中的规则被转换为一个分析表,它有效地表示“如果你有这个输入,并且前瞻记号是X,那么转移到状态Y或者按规则减少R”。yacc/bison LALR(1)算法如何处理“空”规则?
我已经成功构建了解释语言(ruby)中的LALR(1)解析器,不使用生成器,但在运行时计算解析表并使用该解析表评估输入。这种方式出人意料地出色,表格生成相当简单(这让我感到很吃惊),支持自我引用规则和左/右关联。
但是,我有一点难以理解的是yacc/bison在概念上如何处理空白规则定义。我的解析器无法处理它们,因为在生成表格时,它会递归地查看每个规则中的每个符号,而“空白”不是来自词法分析器的东西,也不会被规则所减少。那么,LALR(1)解析器如何处理空的规则呢?他们是专门对待它,还是一个有效的算法应该适用的“自然”概念,甚至不需要特别意识到这样的概念?
比方说,一个规则可以与任何中间匹配任意数量成对的括号:
expr: /* empty */
| '(' expr ')'
;
输入类似下面将匹配这条规则:
((((()))))
这意味着在阅读'('和'看')',在分析器选择:解析器选择:
- 移动')'(不可能)
- 根据一些规则(不可能)
- 别的东西减少输入...
不太适合“移”或“减少”的核心算法。解析器实际上不需要将任何东西移到堆栈上,将“无”减少到expr
,然后移动下一个标记')'
,给出'(' expr ')'
,当然这减少到expr
,依此类推。
这是“没有任何变化”,令我困惑。分析表如何传达这样的概念?还要考虑到应该可以调用一些语义操作,该操作返回值为$$
以减少空值,因此,从分析表跳过该操作并且在堆栈中指示'('
和')'
处于前瞻状态的相当简单的视图应该是只是简单地转换为转换,不会真正产生序列'(' expr ')'
,但只会产生序列'(' ')'
。
我确信[龙书](http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)中有关于处理这些规则的部分很长。我不认为Stack Overflow是讨论它的正确场所 - 也许是程序员? –
感谢您对本书的建议......现在查看该链接。 Stackoverflow似乎是对我来说合适的地方。这是关于算法的直接问题,而不是主观讨论。有人可以很好地寻找这个,如果有人知道答案,快速解决。 – d11wtq
我想我其实只是想到了这一点,当一个基本点出现在我身上时,它是如此明显而直截了当。将回答问题,因为谷歌搜索什么都没有,这是一个相当自然的问题;) – d11wtq