作者回复: LALR(1)比LR(1)的性能要高。实际上,它是LR家族中比较优秀的一个算法了,所以实用度已经比较高,这也是yacc和bison用它的原因。
我再看看文稿,是不是我有什么地方表达得不清楚,引起了你的误解。
另外,我补充几点:
1.就算是LR(1)算法,在处理现代语言的一些语法特征时(泛型、Lamda等),也会产生很多冲突(移进-规约冲突,规约-规约冲突)。所以,用yacc和bison,可以支持实现比较简单的语法,但到了更加复杂的语法,就不够了。
2.GLR是很多人关注的一个LR家族的算法,具有处理冲突的能力。
3.我们课程中讲的单一的算法,无论是LL的还是LR的,在处理复杂的语法时都不够。有语法处理能力的原因,也有处理错误信息方面的考虑。所以,生产环境中支持比较复杂语法的编译器,都不会这么的单线条。GCC之前用过LALR,现在改为纯手写的基于递归下降的(如果我没记错的话...)了。
作者回复: 用状态2中的第一个产生式:start->add.
作者回复: 那个NFA表达了在做正向推导的时候,可能采取的所有可能的推导路径。用了Item这种方式表达出来了而已。
你按照我这种说法看看,是不是那个NFA就代表了示例的语法的推导路径。
把这一关过了,转DFA的过程你肯定是理解的。
作者回复: GCC用过LR,后来用手写的递归下降算法取代了。Clang也是用的手写的递归下降算法。
这说明,递归下降算法真的还是很有实用价值的:-)
用手写代码的好处,是随时可以Hack。就像我们在解决手写实现左结合的时候,就是在做hack。