一、算符优先文法
短语:文法G[S],αβδ是文法G的一个句型,S=>*αAδ且A=>+β则称β是句型αβδ相对于非终结符A的短语。
直接短语:若有A ⇒+⇒+β则称β是句型αβδ相对于该规则A→β的直接短语。
句柄:一个句型的最左直接短语称为该句型的句柄。
短语:一棵子树的所有叶子自左至右排列起来形成一个相对于子树根的短语。
直接短语:仅有父子两代的一棵子树,它的所有叶子自左至右排列起来所形成的符号串。
句柄:一个句型的分析树中最左那棵只有父子两代的子树的所有叶子的自左至右排列。
算符文法的定义:
- 所有产生式的右部都不是ε或两个相邻的非终结符
- 设有一个文法G,如果G中没有形如A→…BC…的产生式,其中B和C为非终结符,则称G为算符文法(Operator Grammar)也称OG文法.
算符优先文法的特点:
- 一旦我们构造了算符优先语法分析器,就可以忽略原来的文法,栈中的非终结符仅仅作为与这些非终结符相关的属性的占位符
- 难以处理像减号这样有不同优先级的符号
- 由于分析的语言的文法和算符优先语法分析器本身的关系不是很紧密,所以不能肯定语法分析器接受的就是所期望的语言
一、首先对于优先关系进行如下定义:
- a的优先级低于b
a < b: 文法中有形如A→…aB…的产生式而B+b…或B+Cb… - a的优先级等于b
a = b: 文法中有形如A→…ab…或者A→…aBb…的产生式 - a的优先级高于b
a > b: 文法中有形如A…Bb…的产生式,而B+…a或B+…aC - 算符的优先关系是有序的
- 如果a > b,不能推出b < a
- 如果a > b,有可能b > a
- 如果a > b, b > c,不一定a > c
根据这个大小关系的定义,我们知道为了确定两个终止符的优先关系,我们需要知道它的在所有的产生式中和前后非终止符的关系,那么我们做一个如(二)预处理:
二、定义并构造FIRSTVT和LASTVT两个集合:
FIRSTVT(P)直接根据定义递归的构造即可:
a) 若有产生式 P→a••• 或 p→Qa•••
则 a∈FIRSTVT(P)b) 若有产生式 P→Q••• ,
若 a∈FIRSTVT(Q)
则 a∈FIRSTVT(P)
LASTVT(P)直接根据定义递归的构造即可:
a) 若有产生式 P→•••a 或 p→•••aQ
则 a∈LASTVT(P)b) 若有产生式 P→•••Q ,
若 a∈LASTVT(Q)
则 a∈LASTVT(P)
三、利用FIRSTVT和LASTVT集合构造算法优先关系表
四、根据算法优先关系表分析各种句子栈内操作
二、LR文法
LL(1)就是向前只搜索1个符号,即与FIRST()匹配,如果FIRST为空则还要考虑FELLOW。 LR需要构造一张LR分析表,此表用于当面临输入字符时,将它移进,规约(即自下而上分析思想),接受还是出错。 LR(0)找出句柄前缀,构造分析表,然后根据输入符号进行规约。 SLR(1)使用LR(0)时若有冲突,不知道规约,移进,活移进哪一个,所以需要向前搜索,则只把有问题的地方向前搜索一次。 LR(1)1.在每个项目中增加搜索符。
概念:
活前缀:不包含句柄右侧任一符号的规范句型的前缀称为该句型的活前缀。
例如:Bab是下面那个文法的一个句型,其中b是句柄。
那么针对这个句型的活前缀有:ε、B、Ba 和Bab
(其实,LR分析器的工作过程实际上就是逐步产生规范句型的活前缀。
如果能构造出一个识别文法所有规范句型活前缀的确定有穷自动机即DFA,就能很方便的构造出LR分析表)
LR(0)项目:右部某位置上标有圆点的产生式称为相应文法的一个LR(0)项目
注意:A --> ε 只对应一个项目 A --> .
(LR(0)项目描述了活前缀和句柄的不同识别状态)
ε-可达:从 S' --> .S 出发,不必再识别任何符号就可以到达 S --> .BB,就称 S --> .BB是从
S' --> .S 出发 ε-可达的。
构造过程:
扩展文法 求出项目集规范族 构造DFA 四、构造LR(0)分析表
三、SLR文法
许多冲突性的动作都可能通过考察有关非终结符的FOLLOW集而获解决。
解决冲突的方法:解决冲突的方法是分析所有含A和B的句型,考察集合FOLLOW(A)和FOLLOW(B),如果这两个集合不相交,而 且也不包含b,那么当状态I面临输入符号a时,我们可以使用如下策略:
若a=b,则移进。
若a∈FOLLOW(A),则用产生式A→α进行归约;
若a∈FOLLOW(B),则用产生式B→α进行归约;
此外,报错*
SLR语法分析表的构造方法:
首先把G拓广为G’,对G’构造LR(0)项目集规范族C和活前缀识别自动机的状态转换函数GO。函数ACTION和GOTO可按如下方法构造:
- 若项目A→α•bβ属于Ik,GO(Ik,a)= Ij,a为终结符,置ACTION[k,a]为“把状态j和符号a移进栈”,简记为“sj”;
- 若项目A→α•属于Ik,那么,对任何非终结符a,a∈FOLLOW(A),置ACTION[k,a]为“用产生式A→α进行归约”,简记为“rj”;其中,假定A→α为文法G’的第j个产生式
- 若项目S’→S•属于Ik,则置ACTION[k,#]为可“接受”,简记为“acc”;
- 若GO(Ik, A)= Ij,A为非终结符,则置GOTO[k, A]=j;
分析表中凡不能用规则1至4填入信息的空白格均填上“出错标志”。
语法分析器的初始状态是包含S’ →•S的项目集合的状态
SLR解决的冲突只是移进-规约冲突和规约-规约冲突
SLR的基本算法:
- 假定LR(0)规范族的一个项目集I中含有m个移进项目
A1→α•a1β1,A2→α•a2β2,…,Am→α•amβm;
同时含有n个归约项目
B1→α•,B2→α•,…,B3→α•, - 如果集合{ a1,…, am},FOLLOW(B1),…,FOLLOW(Bn)两两不相交(包括不得有两个FOLLOW集合有#),则隐含在I中的动作冲突可以通过检查现行输入符号a属于上述n+1个集合中的哪个集合而活的解决:
- 若a是某个ai,i=1,2,…,m,则移进。
- 若a∈FOLLOW(Bi),i=1,2,…,m,则用产生式Bi→α进行归约;
- 此外,报错