如果您想要解析树/森林并且不介意黑盒,GLR 非常棒。它允许您输入任何您想要的CFG,代价是通过详尽的测试在解析时检查歧义,而不是静态地解决 LR/LALR 冲突。有人说这是一个很好的权衡。Ira Baxter 的 DMS 工具或 Elkhound 具有免费的 C++ 语法,对这类问题很有用。ANTLR对于一大类语言应用程序也很有用,但使用自上而下的方法,生成称为 LL(*) 的递归下降解析器,它允许语义谓词。我将在没有证据的情况下声明谓词允许您解析 CFG 之外的上下文相关语言。程序员喜欢在语法中插入动作,喜欢良好的错误处理,喜欢单步调试。LL在这三个方面都很擅长。LL 是我们手工完成的,因此更容易理解。不要相信LR 更擅长处理错误的维基百科废话。也就是说,如果您使用 ANTLR 进行很多回溯,那么使用 LL(*) 的错误确实更糟(PEG 有这个问题)。
重新回溯。GLR 也进行推测(即回溯),就像 PEG、ANTLR 和任何其他非确定性策略一样。在任何不确定的 LR 状态下,GLR “分叉”子解析器以尝试任何可行的路径。无论如何,LL 有很好的错误处理上下文。LR 知道它匹配一个表达式,LL 知道它是一个赋值或条件表达式IF
;LR 知道它可能在任何一个中,但不确定——而这种不确定性正是它获得力量的地方。
GLR 是O(n^3)
最坏的情况。Packrat/PEG 是O(n)
最坏的情况。ANTLR 是O(n^2)
由于循环前瞻 DFA 但O(n)
在实践中。真的没关系。GLR 足够快。
ANTLR是L ang R认知的另一种工具,而不是反 LR,但我也喜欢那个;)
坦白说,和很多 80 后的年轻程序员一样,我不懂 LALR,也不喜欢黑匣子(现在我深挖 GLR 引擎的美,但还是更喜欢 LL)。我构建了一个基于商业 LL(k) 的编译器,并决定构建一个工具来生成我手工构建的内容。ANTLR 并不适合所有人,像 C++ 这样的边缘情况可能会用 GLR 更好地处理,但很多人发现 ANTLR 适合他们的舒适区。自 2008 年 1 月以来,在 ANTLRWorks 中,ANTLR 的二进制 jar 和源 zip 总共有 134,000 次下载(根据 Google Analytics)。请参阅我们关于 LL(*) 的论文,其中包含大量经验数据。