LL和LRparsing有什么区别?
任何人都可以给我一个LLparsing与LRparsing的简单例子吗?
在较高层次上,LLparsing和LRparsing的区别在于,LLparsing器从开始符号开始,尝试应用生成来到达目标string,而LRparsing器从目标string开始并尝试返回到开始符号。
LLparsing是从左到右,最左边的派生。 也就是说,我们从左到右考虑input符号,并尝试构造最左边的派生。 这是通过从开始符号开始并反复扩展最左端的非终结符,直到到达目标string。 LRparsing是从左到右,最右边的推导,也就是说我们从左到右扫描并尝试构build最右边的推导。 parsing器不断地挑选input的子string,并尝试将其反转回非终结符。
在LLparsing期间,parsing器不断在两个操作之间进行select:
- 预测 :根据最左边的非终结符和一些前瞻符号,select应该使用哪个生产来接近inputstring。
- 匹配 :匹配最左边的猜测terminal符号和input最左边的未用符号。
作为一个例子,鉴于这个语法:
- S→E
- E→T + E
- E→T
- T→
int
然后给定stringint + int + int
,一个LL(2)parsing器(它使用两个令牌的前瞻)将parsingstring如下:
Production Input Action --------------------------------------------------------- S int + int + int Predict S -> E E int + int + int Predict E -> T + E T + E int + int + int Predict T -> int int + E int + int + int Match int + E + int + int Match + E int + int Predict E -> T + E T + E int + int Predict T -> int int + E int + int Match int + E + int Match + E int Predict E -> T T int Predict T -> int int int Match int Accept
请注意,在每一步中,我们看看我们生产中最左边的符号。 如果它是一个terminal,我们匹配它,如果它是一个非终结符,我们通过select一个规则来预测它将会是什么。
在一个LRparsing器中,有两个动作:
- Shift :将下一个input标记添加到缓冲区以供考虑。
- 减less :通过反转生产,将此缓冲区中的terminal和非terminal的集合还原到某个非terminal。
例如,一个LR(1)parsing器(带有一个前瞻标记)可能会parsing相同的string,如下所示:
Workspace Input Action --------------------------------------------------------- int + int + int Shift int + int + int Reduce T -> int T + int + int Shift T + int + int Shift T + int + int Reduce T -> int T + T + int Shift T + T + int Shift T + T + int Reduce T -> int T + T + T Reduce E -> T T + T + E Reduce E -> T + E T + E Reduce E -> T + E E Reduce S -> E S Accept
您提到的两种parsingalgorithm(LL和LR)已知具有不同的特征。 LLparsing器往往比手写更容易编写,但是它们不如LRparsing器强大,并且接受比LRparsing器更小的一组语法。 LR语法分析器有很多种(LR(0),SLR(1),LALR(1),LR(1),IELR(1),GLR(0)等等),而且function更加强大。 他们也往往有更复杂的,几乎总是由工具,如yacc
或bison
生成。 LLparsing器也有很多种(包括ANTLR
工具使用的LL(*)),尽pipe在实践中LL(1)是最广泛使用的。
作为一个无耻的插件,如果您想了解有关LL和LRparsing的更多信息,我刚刚完成了一门编译器课程的教学, 并在课程网站上parsing了一些讲义和演讲幻灯片 。 如果你认为它会有帮助的话,我会很乐意详细说明其中的任何一个。
Josh Haberman在他的文章LL和LR Parsing Demystified中声称LLparsing直接对应于波兰语符号 ,而LR则对应于反向波兰语符号 。 PN和RPN之间的差异是遍历方程二叉树的顺序:
+ 1 * 2 3 // Polish (prefix) expression; pre-order traversal. 1 2 3 * + // Reverse Polish (postfix) expression; post-order traversal.
根据Haberman的说法,这说明了LL和LRparsing器的主要区别:
LL和LRparsing器如何操作的主要区别是LLparsing器输出parsing树的预遍历,LRparsing器输出后序遍历。
对于哈伯曼的文章进行深入的解释,举例和结论。