有多少种构建解析器的方法?

How many ways are there to build a parser?

我正在学习 ANTLR v4,它是一个基于所谓的自适应 LL(*) 算法的解析器生成器。它声称是对 LL(*) 算法的重大改进,但我也听说过一些算法,如 LR。

ANTLR 的 Adaptive LL(*) 算法(over LR)的 advantage/limitation 是什么?

How many contemporary algorithms are there to build a parser?

首先可以查看常用解析器生成器列表。
请参阅:Comparison of parser generators 并查看标题 Parsing algorithm.

下的内容
ALL(*)  
Backtracking Bottom-up  
Backtracking LALR(1)  
Backtracking LALR(k)  
GLR  
LALR(1)  
LR(1)  
IELR(1)  
LALR(K)
LR(K)  
LL  
LL(1)
LL(*)  
LL(1), Backtracking, Shunting yard
LL(k) + syntactic and semantic predicates  
LL, Backtracking  
LR(0)  
SLR  
Recursive descent  
Recursive descent, Backtracking  
PEG parser interpreter, Packrat  
Packrat (modified)  
Packrat  
Packrat + Cut + Left Recursion  
Packrat (modified), mutating interpreter  
2-phase scannerless top-down backtracking + runtime support  
Packrat (modified to support left-recursion and resolve grammar ambiguity)  
Parsing Machine  
Earley  
Recursive descent + Pratt  
Packrat (modified, partial memoization)  
Hybrid recursive descent / operator precedence  
Scannerless GLR  
runtime-extensible GLR  
Scannerless, two phase  
Combinators  
Earley/combinators  
Earley/combinators, infinitary CFGs  
Scannerless GLR  
delta chain  

除了解析器生成器,还有其他algorithms/means可以解析。特别是 Prolog 有 DCG and most people who have written their first parser from scratch without formal training typically start with recursive descent. Also Chart parser and Left corner parser.

在编写解析器时,我总是问自己的第一个问题是如何为 Chomsky hierarchy 中最高类型的语言编写语法。这里最低的是 Type-0,最高的是 Type-3。

几乎 90% 的时间它是 Type-2 语法 (context-free grammars), then for the easer task it is a Type-3 grammar (regular grammars). I have experimented with Type-1 grammars (context-sensitive grammars) and even Type-0 grammars (unrestricted grammars)。

And what's the advantage/limitation of ANTLR's Adaptive LL(*) algorithm?

参见 Adaptive LL(*) 的创建者 Terrence Parr 撰写的论文: Adaptive LL(*) Parsing: The Power of Dynamic Analysis

实际上,Adaptive LL(*) 可以让您更快地从语法到工作解析器,因为您不必了解那么多的解析理论,因为 Adaptive LL(*) 足够灵活,可以避开你在语法中不知不觉放置的地雷。这样做的代价是,您在语法中不知不觉地放置了一些地雷,可能会导致解析器运行时效率低下。

对于大多数实用的编程语言而言,Adaptive LL(*) 就足够了。 IIRC Adaptive LL(*) 不能执行 Prolog DCG 可以执行的 Type-0 语法(unrestricted grammars),但正如我所说,大多数人和最常见的编程任务只需要类型 2 或类型 3。

大多数解析器生成器也适用于类型 2,但这并不意味着它们不能做类型 1 或可能类型 0。我不能更具体,因为我没有所有这些的实践经验。

无论何时使用解析工具或库,都存在一个学习曲线来学习如何使用它以及它能做什么和不能做什么。

如果您是 lexing/parsing 的新手并且真的想更深入地了解它,那么请参加课程 and/or 阅读 Compilers: Principles, Techniques, and Tools (2nd Edition)