1、3.5 LR分析器,LR(k):L表示从左至右扫描输入串,R表示构造一个最右推导的逆过程,k指的是在决定语法分析动作时需要向前看的符号个数。 LR分析法的缺点:手工实现工作量大 构造LR分析表的方法 简单LR方法(SLR) 规范的LR方法 向前搜索的LR文法(LALR) 描述能力:规范LRLALRSLR 实现代价:规范LRLALRSLR,3.5.1 LR分析算法,LR分析 程 序,LR分析器模型,栈,语法分析表,分析表构成:动作表(action)和转向表(goto) 注:Si表示状态, ai表示终结符,Ai表示非终结符。,action goto,actions,a规定了状态s面临输入符号a时应
2、该采取什么动作: 移进:把(s,a)的下一状态s=gotos,a和输入符号a推进栈,下一输入符号变成现行输入符号; 归约:指用某一产生式A进行归约。 接受:宣布分析成功,停止分析器的工作; 报错:报告发现错误,调用出错处理程序扫描输入串就可以发现错误位置。,gotos,X则指出状态s面对文法符号X(终结符或非终结符)时下一状态是什么。 gotos,X:若X VT ,表示在当前状态下,读入X应转向什么状态;若X VN ,表示当前栈顶句柄归约成X后,应转向什么状态。,( so X1 s1 . Xm sm, ai ai+1 . an $ ) 分析器根据action(sm , ai)确定下一步动作 1
3、. 若action(sm , ai)为移进,且s=gotosm,ai,则二元式格局变为: (s0 X1 s1 Xm sm ai s, ai+1 an $) 2. 若action(sm , ai)为按A归约,二元式变为:(s0 X1 s1 Xm-rsm-r A s, aiai+1 an $) 此处, s=goto(sm-r, A), r为的长度, = Xm-r+1 Xm 3. 若action(sm , ai)为“接受“,则二元式不再变化,变化过程终止,宣布分析成功。 4. 若action(sm , ai)为“报错“,则二元式变化过程终止,报告错误。,算法3.3 LR分析算法,令a指向$的第一个符
4、号; while(1) 令s是栈顶的状态;if (actions,a=“移进t “) 把a和t依次压入栈顶;a指向下一个输入符号;else if (actions,a=“按文法产生式A归约 “) 从栈顶弹出2*|个符号;令t是现在的栈顶状态;把A和gotot,A依次压入栈顶;输出产生式A;else if (actions,a=“接受“) break; /*分析完成*/else error(); ,例:文法G(E):(1) EET (2) ET (3) TT*F (4) TF (5) F(E) (6) Fid 分析id*id+id的识别过程。,其LR分析表为:,si表示把当前符号和状态i压入栈
5、rj表示按第j个产生式归约 acc表示接受 空白表示出错,栈 输入 动作 输出 0 id*id+id$ s5 0id5 *id+id$ 用 Fid归约 Fid 0F3 *id+id$ 用 TF归约 TF 0T2 *id+id$ s7 0T2*7 id+id$ s5 0T2*7id5 +id$ 用 Fid归约 Fid 0T2*7F10 +id$ 用 TT*F归约 TT*F 0T2 +id$ 用 ET归约 ET 0E1 +id$ s6 0E1+6 id$ s5 0E1+6id5 $ 用 Fid归约 Fid 0E1+6F3 $ 用TF归约 TF 0E1+6T9 $ 用 EE+T归约 EE+T 0E1
6、 $ 接受,3.5.2 LR文法和LR分析方法的特点,对于给定文法G,如果能为G构造出LR语法分析表,则称G是LR文法。 LR语法分析器不需要扫描整个栈就可以知道什么时候句柄出现在栈顶,栈顶的状态符号包含了所需要的一切信息。 gotos,X定义了一个以文法符号为字母表的DFA。,每步需要向前看k个符号的LR语法分析器所分析的文法称为LR(k)文法 一般k=0或k=1,LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA 栈顶的状态符号包含了确定句柄所需要的一切信息 是已知的最一般的无回溯的移进归约方法 能分析的文法类是预测分析法能分析的文法类的真超集
7、 LR分析法的缺点:手工实现工作量大,3.5.3 构造SLR分析表,构造分析表的基本策略: 构造文法G的一个有限自动机,它能识别文法中的所有活前缀。 字的前缀是指该字的任意首部。 例如:字ABC的前缀有,A,AB,ABC。 活前缀(Viable Prefix)是指规范句型的一个前缀,这种前缀不含句柄之后的任何符号。,活前缀有两种类型: 1)归态活前缀 活前缀的尾部正好是句柄之尾,这时可以进行归约。归约之后又成为另一句型的活前缀。 2)非归态活前缀 句柄尚未形成,需要继续移进若干符号之后才能形成句柄。,在LR分析过程中的任何时候,栈里的文法符号(自栈底向上)X1X2Xm应该构成活前缀,把输入串的
8、剩余部分配上之后即应成为规范句型(当然,这个输入串必须确实是文法的一个句子)。反过来说,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着扫描过的部分没有错误。,构造出一个FA,它能识别某文法G的所有活前缀 可以文法的终结符和非终结符都看成有穷自动机的输入符号,每次把一个符号进栈看成已识别过了该符号,同时状态进行转换,当识别到可归前缀时,相当于在栈中形成句柄,认为达到了识别句柄的终态。,项目,项目(item):在每个产生式的右部适当位置添加一个圆点构成项目 例如:产生式A XYZ对应有4个项目 A XYZ A XYZ A XYZ A XYZ 产生式A只有一个项目A。 有限自动机的每一个状
9、态由一个项目构成,项目圆点的左部表示分析过程的某个时刻用该产生式归约时句柄已识别的部分,圆点右部表示待识别的部分。,拓广文法,如果文法G的开始符号是S,那么G的拓广文法G是在文法G的基础上增加一个新的开始符号S和产生式SS。 将文法进行拓广,保证文法开始符号不出现在任何产生式右部,即增加产生式SS ,并令S S作为初态项目,闭包运算closure,如果I是文法G的一个项目集,定义和构造I的闭包closure(I)如下: 1)I的项目都在closure(I)中 2)若A B属于closure(I),则每一形如B 的项目也属于closure(I) 3)重复2)直到closure(I)不再扩大,cl
10、osure的计算,function closure ( I ) beginJ := I;repeat for J 的每个项目 A .B 和G的每个产生式B ,若 B. 不在 J中 do把 B. 加入 J;until 没有新项目可加入 J;return J end,例:对于以下文法,计算closure(E E) E E E E+T E T T T*F T F F (E) F id,closure(E E) = E E E E+T E T T T*F T F F (E) F id ,核心项目:初始项目和所有圆点不在左端的项目 非核心项目:圆点在左端的非初始项目,goto函数,定义转换函数如下: g
11、oto(I,X)= closure(J) 其中:I为某项目集,X为文法符号 J=任何形如AX 的项目| A X 属于I 如果I是对某个活前缀有效的项目集,那么goto(I,X)是对活前缀X有效的项目集。,例:若I=E E, E E+T,则goto(I,+)为 E E+T T T*F T F F (E) F id,项目集的构造,procedure items(G); beginC:= closure( SS ) ;repeatfor C中的每个项目集I和G中的每个符号X DOIF goto(I,X)非空且不属于C THEN把goto(I,X)放入C中until C不再增大 end,文法3.11的
12、项目集规范族,I0: EE EE+TET TT*FTT*FTFF (E) Fi,I1: EE EE+T,I2: ET TT*F,I3: TF,I4: F(E) EE+TETTT*FTFF (E)Fi,I5 : Fi,I6: EE+TTT*FTFF(E)Fi,I7: TT*FF(E)Fi,I8: F(E)EE+T,I9: EE+T TT*F,I10: TT*F,I11: F(E),文法3.11的goto函数,SLR语法分析表,1.构造G的LR(0)项目集规范族C=I0,I1,.,In 2.从Ii构造状态i,它的分析动作如下: a)若项目Aa属于Ii且GO(Ii,a)=Ij,a为终结符,则置actioni,a为 “sj”; b) 若项目A属于Ii,那么,对任何终结符a,aFOLLOW(A),置actioni,a为 “rj”;其中,假定A为文法G的第j个产生式; c) 若项目SS属于Ii,则置ACTIONi,$为“acc”;,3.对所有非终结符A,若goto(Ii,A)Ij,则置gotoi,A=j; 4.分析表中凡不能用规则2,3填入信息的空白格均置上“出错标志”。 5.语法分析器的初始状态是从包含SS的项目集构造出的状态。,(P70),