摘要:升级前文的LR(1) parser generator为GLR,为自制脚本语言加入面向对象、泛型模板和函数式编程等语法做好准备。
源代码地址: www.github.com/nklofy/Compiler
LR(1) parser为前文的自制脚本语言立下了汗马功劳。但是脚本语言不能只满足于C的子集,至少应该OOP类型继承、泛型要加入吧,甚至lambda表达式和函数式编程也要加入吧。那样LR(1)就不够用了。一个比较快捷的方法是,LR(1)升级到GLR。parser generator只需要少量修改,parser需要将原来的符号栈改为栈图。目前,parser generator和parser已经完成。
GLR parser,是可以容许shift-reduce冲突、reduce-reduce冲突的LR解析方法。它的基本思想是:每次读入一个token作为前瞻符号,执行reduce和shift,如果遇到shift-reduce冲突或reduce-reduce冲突,就暂时保留所有可能的parsing路线,当遇到reduce或shift都不能执行,则去掉该parsing线路。当最终读取eof并规约到goal时,parsing结束。比起LR(1),因为有大量的可能路线同时存在,全部都要执行shift和reduce,其实可能只有一条正确的路线,这样就导致大量时间浪费,效率差。
在Elkhound的论文<A fast, parctical GLR parser generator>中,提出了几种优化GLR的办法。其中最重要的是GLR和LR的切换。在某些情况下,只有单线parsing向前推进,这种情况下,reduce可以采用LR的规约方式,即直接向前查找。当遇到分岔路时,必须采用GLR的规约方式。另外,Elkhoun