1
akfish 2014-04-18 17:52:07 +08:00
这样就形成左递归了,会导致递归下降分析器无限递归。
|
2
cocorosiekz 2014-04-18 18:03:14 +08:00
LL(1)的不能解析这种语法,SLR的就无所谓了
|
3
ibudao OP @cocorosiekz 那为什么LR的文法我看到的都是用这种左递归呢,还是说写成有递归也是可以的?
|
4
ibudao OP @cocorosiekz 那为什么LR的文法我看到的都是用这种左递归呢,还是说写成右递归也是可以的?
|
5
cocorosiekz 2014-04-18 19:11:21 +08:00
@ibudao 我觉得LR文法可以处理左递归,是因为本身是bottom-up的,shift\reduce的方式本身不存在这个问题
|
6
ibudao OP @cocorosiekz 在维基上找到答案了。A formal grammar that contains left recursion cannot be parsed by a LL(k)-parser or other naive recursive descent parser unless it is converted to a weakly equivalent right-recursive form. In contrast, left recursion is preferred for LALR parsers because it results in lower stack usage than right recursion.
|
7
cocorosiekz 2014-04-18 23:21:28 +08:00
@ibudao 恩,这里没有解释为什么左递归和右递归的gammar可以用到bottom-up中,可能比较直白了吧,关于左递归和右递归对栈的消耗高低是对的,这个具体写一下就可以明白
|
8
chengluyu 2014-04-19 20:03:17 +08:00 via iPad 1
因为加号是一个左结合的操作符,就是说1+1+1+1=(((1+1)+1)+1)。
结合性的重要性在加号上体现的不明显,因为加法无论怎么结合答案都一样,但是如果是减法就不一样了: 1-1-1-1-1-1=(((((1-1)-1)-1)-1)-1),但是不等于((1-1)-(1-1)-(1-1))。 所以把product放在左边就是为了符合操作符的左结合性。 顺便一提,如果你熟悉Haskell这样的函数式语言,你会发现这个和foldl和foldr很像。 |
9
chengluyu 2014-04-19 20:04:46 +08:00 via iPad
至于左递归,只要用消除左递归的法则消除就可以使用递归下降的方法进行语法分析了。
|
10
ibudao OP @chengluyu 对的,我是erlang程序员,在erlang中也有foldl和foldr。但是,如果左递归是为了表达操作符的左结合性,右递归是为了表达右结合行,我好奇的是LL(k)解析器是如何消除左递归,而又能表达操作符的左结合性的?
|
11
Golevka 2014-04-20 01:41:32 +08:00
chengluyu关于结合性的说明是正确的,虽然不同的CFG能产生同样的集合但是对应的parse tree不同,于是解析出的AST是不一样的,比如1 - 2 + 3这个case就能放倒一大片结合性做杯具了的parser:
correct: (+ (- 1 2) 3) incorrect: (- 1 (+ 2 3)) |