1、主要思想:
对文法按一定规则,求Vt(终结符)之间的关系,再按照这种关系来确定句柄。(通俗来讲就是不要管非终结符)
2、步骤:
- 拓广文法:S'-->#S#
- 构造算符优先关系表
- 判断是否为算符优先文法(OPG文法)
- 根据优先关系表分析句子
3、优先函数:
为了节约存储空间,用“优先函数”代替“优先关系表”
4、算符文法的定义:
算符文法:上下文无关文法G中没有形如A-->...BC...的产生式,则称OG文法。(就是说产生式右部不存在相邻的两个非终结符)
性质1:任何句型都不包含两个相邻的非终结符
性质2:如Ab/bA(终结符和非终结符相邻)出现在算符文法的句型中,则任何包含b的短语比包含有A。(但含A的未必含b)
5、算符优先关系的定义:
(1)a=b: 含有形如A-->...ab...或a-->...aBb的产生式
(2)a<b: 含有形如A-->...aB...的产生式,B至少一次推导出b...或Cb...
(3)a>b: 含有形如A-->...Bb...的产生式,B至少一次推导出...a或...aC(以终结符结尾或终结符带非终结符结尾)
6、算符优先关系表的构造
定义法 构造算符优先关系表:
(1)定义:FirstVT和LastVT
FirstVT(B) = {b|B有限次推导出以b...终结符b开头/以Cb...开头}
LastVT(B) = {a|B有限次推导出...a以(以终结符a结尾)...aC(或带一个非终结符)}
(2)求优先关系
a=b A-->...ab.../A--->...aBb...
a<FirstVT(B) A-->...aB...
LastVT(B)>c A-->...Bc...
(3)构造优先关系表
步骤:
- 计算每个Vn的FirstVt集和LastVt集
- 求优先关系:
- 求=关系
- 求<关系:找...aB... a<FirstVT(B)
- 求>关系:找...Bc... LastVT(B)>c
3.构造优先关系表
例1:
有文法G[E]:
E-->E+T
E-->T
T-->T*F
T-->F
F-->P^F
F-->P
P-->(E)
P-->i
步骤一:拓广文法:
S'-->#E#
E-->E+T
E-->T
T-->T*F
T-->F
F-->P^F
F-->P
P-->(E)
P-->i
步骤二:求FirstVT和LastVT:(从叶子节点找比较方便)
FirstVT | LastVT | |
E' | # | # |
E | ( i ^ * + | ) i ^ * + |
T | ( i ^ * | ) i ^ * |
F | ( i ^ | ) i ^ |
P | ( i | ) i |
步骤三: 求优先关系:
=关系:#=#、(=)
<关系:找...aB... a<FirstVT(B):
#E:#<( #<i #<^ #<* #<+
+T:+<( +<i +<^ +<*
*F:*<( *<i *<^
^F:^<( ^<i ^<^
(E:(<( (<i (<^ (<* (<+
>关系:找...Bc... LastVT(B)>c:
E#:)># i># ^># *># +>#
E+:)>+ i>+ ^>+ *>+ +>+
T*: )>* i>* ^>* +>*
P^: )>^ i>^
E): )>) i>) ^>) *>) +>)
构造算符优先关系表:
+ | * | ^ | ( | ) | i | # | |
+ | > | < | < | < | > | < | > |
* | > | > | < | < | > | < | > |
^ | > | > | < | < | > | < | > |
( | < | < | < | < | = | < | |
) | > | > | > | > | > | ||
i | > | > | > | > | > | ||
# | < | < | < | < | < | = |
7、算符优先文法的定义
1. 设有一个不含产生式的算符文法G,如果对于任意两个终结符a和b之间至多只有=,<,>三种关系的一种成立,则称G是一个算符优先文法(OPG)
特点:
- 不含空产生式
- 任何产生式右部不包含两个相邻的非终结符
- 任何两个终结符之间优先关系唯一
2. 算符优先文法是无二义性的。
例2:
有文法:
E'-->#E#
E-->E+T|T
T-->T*F|F
F-->F^P|P
P-->(E)|i
+ | * | ^ | ( | ) | i | # | |
+ | > | < | < | < | > | < | > |
* | > | > | < | < | > | < | > |
^ | > | > | < | < | > | < | > |
( | < | < | < | < | = | < | |
) | > | > | > | > | > | ||
i | > | > | > | > | > | ||
# | < | < | < | < | < | = |
分析句子 #i+i#
步骤 | 栈 | 优先关系 | 当前符号 | 待输入串 | 动作 |
1 | # | < | i | +i# | 移进 |
2 | #i | > | + | i# | 归约i<--P |
3 | #S(终结符忽略用S代替,下同) | < | + | i# | 移进 |
4 | #S+ | < | i | # | 移进 |
5 | #S+i | > | # | 归约i<--P | |
6 | #S+S | > | # | 归约S+S<--E | |
7 | #S | = | # | 接受 |
归约时:往前比较关系,直到遇到小于,小于右边为句柄头,开始为句柄尾
8、算符优先分析
规约过程中,只考虑终结符之间的优先关系来确定句柄,而与非终结符无关。这样去掉了单个非终结符的归约,不是规范归约。
9、最左素短语
- 素短语:设有文法G[S],其句型的素短语是一个短语,它至少包含一个终结符,且除自身外不在包含其他素短语。
- 最左素短语:句型最左边的素短语。例子:
素短语:T*F i
最左素短语:T*F (树中靠最左边)
10、算符优先分析的局限性
简单优先分析:是规范归约,关键是寻找句柄。
算符优先分析:不是规范归约,关键是寻找最左素短语。(会出现“错误的句子得到正确的归约”,一般语言的文法难满足算符优先分析的条件)
所以,算符优先文法分析只适用于表达式的语法分析
11、优先函数
- 优点:优先函数比优先矩阵节省空间
- 缺点:当发生错误的时候不能准确指出错误位置
- 优先函数的构造方法:
1、由定义直接构造
2、用关系图构造优先函数
例子:
+ | * | i | |
+ | > | < | < |
* | > | > | < |
i | > | > |
优先关系图:横为g,列为f(由大指向小,=则双向箭头)
优先关系表:可经过的节点数(自身算一个节点)