经过前面两篇文章。已经讲清楚了LR语法分析中最重要的分析表的构造过程。先补充一个小问题,就是LR(0)项目的分类
根据圆点所在的位置和圆点后是终结符还是非终结符或为空把项目分为以下几种:
移进项目: 形如 A→α .a β ,a是终结符, a ,b∈V* 以下同
待约项目:A→α .B β , 其中B是非终结符
归约项目:A→α . 表明产生式已分析完成。
接受项目:形如 S’→S .
特别的。A→ε的LR(0)项目只有A→ • 是归约项目
因为LR分析表的构造前面两篇文章已经讲的很清楚了,所以这个题目重要是解释一下如何使用分析表来构造,分析表的构造也许你得自己参考前面两篇文章来构造了。题目来自网络。
好,下面看题目,已知文法G[S]:
(1) S → aAcBe
(2) A → b
(3) A → Ab
(4) B → d
写出对输入串 abbcde#的LR分析 过程。
在分析的时候,因为我们的手工分析,所以还需要一个表来记录我们的步骤。否则记不住啊。该表共需7列。行数不定。做到哪是哪。
步骤 | 符号栈 | 输入符号栈 | 动作 | 状态栈 | ACTION | GOTO |
其中,步骤就是从1向下递增。符号栈用来保存运算中的结果,初始为#,输入符号栈保存输入串,初始值为给定的。动作里面就是用来注释是进行移进,还是规约。状态栈就是保持LR分析表的那个状态了。Action 和Goto同理
通过前两篇文章的步骤,此题可以构造出如下的一张LR分析表
分析表中有Si和rj大家都知道的。s是shift的缩写,也就是移进,r是reduce的缩写,也就是规约。规约是推导的逆操作,大家都懂。
先来看看在进行分析的时候s和j操作的规则
Si:移进,把i移入到状态栈,把a移入到文法符号栈。其中i,j表示状态号。
ri:归约,用第i个产生式归约,同时状态栈与符号栈退出相应个符号,并把GOTO表相应状态和第i个产生式的左部非终结符入栈。
文法中有A→β的产生式,若β的长度为r(即|β|=r),则从状态栈和文法符号栈中自栈顶向下去掉r个符号,即栈指针P减去r。并把A移入文法符号栈内,Sj=GOTO[Si,A]移进状态栈,其中Si为修改指针后的栈顶状态。
当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是’#',则为分析成功。
然后使用我们将要使用的辅助表来分析吧,为了简单。我还是直接给出答案。然后分析一下典型的情况。
第一步,符号栈中是#,输入符号串就是给定的要分析的串,状态栈因为从0开始,所以状态栈直接填0,大家都知道,LR分析是从左到右扫描的。所以心里想着一根指针p,p首先指向输入串的a,然后我们查分析表的(0,a),0就是状态0,a就是指针的当前字符。分析表中的(0,a)是s2,填入第一步的action,并且动作列填入移进,根据规则,将2入状态栈,a入符号栈,
进入第二步,指针p肯定要前进一步了,所以输入符号串就进入b了。此步同上一步,不多解释。
关键是进入第三步后,此时,符号栈中为#ab,输入符号串是bcde#,状态栈是024,此时去查表,差的是(4,b),4是状态栈顶,b是p指针的当前位置。发现是r2,根据规则,用第二条产生式(2) A → b来规约。把动作栏先填了,同时状态栈与符号栈退出相应个符号,也即是说,把状态栏的栈顶4,退出来,同时符号栈的b也退出,心里想着,不填表,并把GOTO表相应状态和第i个产生式的左部非终结符入栈。Goto表需要查的是(2,A)=3,2是r2的2,A是第二个产生式的左部嘛。所以,就把3入状态栈,A入符号栈。
后面的都是一样的。不解释了。要想学懂编译原理。多动手是必需的。你也手工试试吧。
参考:
http://leaver.me/archives/574.html
http://leaver.me/archives/548.html