【发布时间】:2011-11-23 12:53:05
【问题描述】:
在 LALR(1) 解析器中,语法中的规则被转换为一个解析表,该表有效地表示“如果到目前为止你有这个输入,并且前瞻标记是 X,那么转移到状态 Y,或者减少规则 R"。
我已经成功地用解释语言 (ruby) 构建了一个 LALR(1) 解析器,而不是使用生成器,而是在运行时计算解析表并使用该解析表评估输入。这工作得非常好,而且表生成非常简单(这让我有些惊讶),支持自引用规则和左/右关联。
然而,我难以理解的一件事是 yacc/bison 在概念上如何处理空规则定义。我的解析器无法处理它们,因为在生成表时,它会递归地查看每个规则中的每个符号,并且“空”不是来自词法分析器的东西,也不会被规则减少。那么,LALR(1) 解析器如何处理空规则呢?他们是否特别对待它,或者它是一个有效算法应该使用的“自然”概念,甚至不需要对这样一个概念有特别的认识?
比方说,一条规则可以匹配任意数量的成对括号,中间没有任何内容:
expr: /* empty */
| '(' expr ')'
;
如下输入将匹配此规则:
((((()))))
这意味着在前瞻标记中读取 '(' 并看到 ')' 时,解析器会选择:
- 移动 ')'(不可能)
- 根据其他规则减少输入(不可能)
- 别的东西...
不太适合“shift”或“reduce”的核心算法。解析器实际上需要什么都不移动到堆栈上,将“无”减少到expr,然后移动下一个标记')',给出'(' expr ')',当然这减少到expr,等等。
让我困惑的是“什么都不做”。解析表是如何传达这样一个概念的?还考虑到应该可以调用一些语义操作,在减少空值时将值返回到$$,因此只是从解析表中跳过它并说堆栈上的'(' 和@前瞻中的 987654330@ 应该简单地转换为移位,不会真正产生序列 '(' expr ')',而只会产生序列 '(' ')'。
【问题讨论】:
-
我确信dragon book 中有很长的部分是关于处理此类规则的。我不认为 Stack Overflow 是讨论它的合适场所——也许是程序员?
-
感谢您对本书的建议...现在查看该链接。 Stackoverflow 对我来说似乎是正确的地方。这是关于算法的直接问题,而不是主观讨论。有人可以很好地搜索这个,如果有人知道答案,请快速解决。
-
我想我实际上是在我意识到一个基本点时才意识到这一点的,而且它是如此的明显和直截了当。会回答问题,因为谷歌搜索什么都没有,这是一个相当自然的问题;)