我正在学习ANTLR v4,它是一个基于所谓的自适应LL(*)算法的解析器生成器。它声称是对LL(*)算法的重大改进。但我也听说过像LR这样的算法。
所以,出于好奇而得到一张大图:
答案 0 :(得分:5)
有多少现代算法可以构建解析器?
首先,可以查看常用解析器生成器的列表
请参阅: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),然后对于easer任务,它是Type-3语法(regular grammars)。我已尝试使用Type-1语法(context-sensitive grammars)甚至Type-0语法(unrestricted grammars)。
ANTLR的自适应LL(*)算法的优势/局限是什么?
请参阅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的新手,并且真的想更多地了解它,那就选择一门课程和/或阅读Compilers: Principles, Techniques, and Tools (2nd Edition)