有多少现代算法可以构建解析器?
首先可以查看常用解析器生成器的列表。
请参阅: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
除了解析器生成器之外,还有其他算法/方法可以解析。特别是 Prolog 有DCG,大多数没有经过正式培训就从零开始编写第一个解析器的人通常以recursive descent 开头。还有Chart parser 和Left corner parser。
在编写解析器时,我总是问自己的第一个问题是如何为Chomsky hierarchy 中最高类型的语言编写语法。这里最低的是Type-0,最高的是Type-3。
几乎 90% 的时间它是 Type-2 语法 (context-free grammars),然后对于更简单的任务它是 Type-3 语法 (regular grammars)。我已经尝试过 Type-1 语法 (context-sensitive grammars) 甚至 Type-0 语法 (unrestricted grammars)。
ANTLR 的 Adaptive LL(*) 算法的优势/局限是什么?
参见Terrence ParrAdaptive LL(*)的创建者写的论文:
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。我不能更具体,因为我对所有这些都没有实际经验。
每当您使用解析工具或库时,都有一个学习曲线来学习如何使用它以及它可以做什么和不能做什么。
如果您不熟悉词法分析/解析并且真的想进一步了解它,请参加课程和/或阅读Compilers: Principles, Techniques, and Tools (2nd Edition)