赞
踩
自下而上的语法分析方法:
就是从给定的字符串出发,逐步向上规约,直至文法的开始符S,看能否找到一个最左规约序列。
具体方式:
采用一个存放文法符号的栈,把输入字符串的符号逐个压栈,随时观察栈顶的情况,当栈顶形成某个产生式的一个候选式时,就把这一部分出栈,将该产生式的左端符号压栈,即规约。如此不断地“移进—规约”分析,直到输入符号串移进完,且栈里仅剩下文法开始符为止。
例如:
怎么判断栈里已经形成了可规约串?
下面重点讨论LR分析法。
LR分析过程:
采用一个下推栈,用来存放已移进(的终结符)和规约(的非终结符)的符号串,该符号串看成“历史”;当前准备移进栈的符号看成“现在”;推测将来可能碰到的移进栈的符号串,将其看成“将来”。
LR分析器根据“历史”,“现在”和“将来”判断栈顶是否已经形成句柄,从而确定本次分析应该采取的动作是:规约,移进或语法出错。
然而,在某些状态下,会出现既可以移进也可以规约的情况,或有两个以上不同的规约的情况,称为“移进—规约”冲突,或“规约—规约”冲突。
例如:
LR(K)文法的定义:
一个文法,如果能用一个每步顶多向前检查k个输入符号的LR分析器进行分析,则这个文法就称为LR(K)文法。
通常只讨论K≤1的情况。
K≤1的LR分析器可分为:LR(0),SLR(1),LALR(1),LR(1)。
其中,
LR(0)分析能力最弱,只对无冲突的文法有效;
SLR(0)可采用简单的方法解决冲突;
LALR(1)分析能力较强;
LR(1)分析能力最强,可采用精确的方法解决冲突。
下面重点讨论LR(0)和SLR(1)。
首先解释一下LR分析器进行语法分析的详细过程,之后再讨论LR(0)和SLR(1)。
LR分析器的结构:
LR分析器的分析过程:
设文法G如下:
则可以得到LR分析表如下:
举例说明:i+i*i 的分析过程
很好理解,一开始状态为0,然后根据输入的字符在LR分析表里找到对应的动作进行操作,直到ACC说明语法分析成功。
由此可见,利用LR分析表就可以进行语法分析了,所以问题的关键在于如何构造LR分析表。
在开始构造LR分析表之前,需要了解一些概念做准备。
句柄的定义:
S是文法G的开始符号,假定αAδ是文法G的一个句型,如果有
则称β是句型αβδ关于非终结符A的短语。
特别地如果存在产生式A→β,则称β是句型αβδ关于非终结符A的直接短语。
一个句型的最左直接短语称为该句型的句柄。
个人理解:
简单来说,某个句型取一段符号串,如果该符号串能(根据文法)被规约,那么该符号串就是直接短语。
句柄就是在所有直接短语中选取的最左直接短语。
例如:
有句型abbcde,文法中有A→b,那么该句型的句柄就是b;
有句型aAbcde,文法中有A→Ab,那么该句型的句柄就是Ab;
活前缀的定义:
规范句型中不含句柄之后任何符号的一个前缀。
即:从第一个符号开始,到句柄结束,构成了一个符号串,这符号串的前缀叫做该规范句型的活前缀。
活前缀与句柄之间的三种关系:
项目的定义:
A→•αβ,A→α•β,A→αβ•
圆点可以看作栈内外的分界线。
在文法G的产生式不同位置加圆点为文法G的一个LR(0)项目,简称项目。
项目的分类:
拓广文法:
对文法G(S),增加产生式S’→S,把开始符号重新表示为S’,形成拓广文法G(S’)。
在该拓广文法中, 项目S’→S•是唯一的接受项目。
有效项目集:
对活前缀δα有效的项目的集合称为对δα的有效项目集。
如果从初态到达状态A→α•β时,δα已识别出,希望继续从输入串中识别由β推出的串,则称项目A→α•β对活前缀δα有效。
有效项目集闭包closure(I)的求法:
设I是文法G的一个项目集,通过以下步骤构造有效项目集闭包closure(I):
项目集规范族的定义:
一个文法G的所有有效项目集组成的集合,叫做该文法G的项目集规范族。
项目集规范族C的求法:
begin
C : = { closure ( { S’→•S } ) };
repeat
for( C中每一项目集I和符号X, X∈V* )
do { if ( go(I, X)∉C ) then 把go(I, X)加入C中 }
until C不再增大
end
举例说明:
设经过拓广后的文法G如下:
求它的LR(0)项目集规范族的过程:
其中:
每一个方框就是一个状态,对应一个项目集I;
每一个箭头对应状态转换的文法符号X。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。