算符优先文法构建优先关系表
声明:
本文仅供参考,若有异议,可加评论,我愿积极吸取各位大佬意见
基本思想
算符优先文法
概念:一个文法,如果它的任一产生式的右部都不含有两个相继并列的非终极符,及不含有以下大的格式
.................QR.......................
我们就称该文法为算符文法。
构建两个集合
FIRSTVT(P) 和LASTVT(P)
概念:
FIRSTVT(P) = {a | P
a....或 P
Qa.......,a
而Q
}
LASTVT(P) = {a | P
... 或 P
....aQ,a
而Q
}
其中Vt是终结符,Vn是非终结符
通过这两个关系,就能了解到了对应的数据之间的联系
构建优先关系表
通过LASTVT(P)和FIRSTVT(P)找到了终结符之间的>和<(这里的大和小不是数学上的关系大小比较)。
优先关系表
举个例子:
+ | * | ↑ | i | ( | ) | # | |
---|---|---|---|---|---|---|---|
+ | > | < | < | < | < | < | > |
* | < | < | < | > | > | > | > |
↑ | < | > | > | > | > | > | > |
i | < | < | < | > | < | ||
( | < | > | > | < | > | = | < |
) | < | > | < | > | < | > | |
# | < | < | < | < |
通过这些大致对于优先关系表以及算符优先文法有了大致的了解
实现操作
例如:
E -> E + T | T
T - > T * F | F
F -> P ↑F | P
P ->(E) | i
确定集合
确定FIRSTVT
由以上的例子可以找
这里我的理解是对于非终结符E->E + 找到对应的终结符,以下同理T ->T*,...........
(1)根据P- >Q a(上面的集合介绍)可以找到终结符(第一个非终结符)
E->E + T
可以找到E的终结符+
T->T * F
可以找到T的终结符*
F -> P↑F
可以找到F的终结符↑
P->(E) | i
可以找到P的终结符( 和 i
(2)根据P->Qa(找到递归中的FRISTVT(P)
E->T
需要找FIRSTVT(E),就需要找FIRSTVT(T)
T-> F
需要找FIRSTVT(T),就需要找FIRSTVT(F)
F->P
需要找FIRSTVT(F),就需要找FIRSTVT(P)
P -> (E) | i
第一步已经找到了对应的FIRSTVT(P)
(3)第一步加上第二步得到最后的结果
FRISTVT(E) = {+,*,↑,(,i};
FIRSTVT(T) = {*,↑,(,i};
FIRSTVT(F) = {↑,(,i};
FIRSTVT(P) = {(,i};
确定LASTVT
这里对于LASTVT寻找的理解是E->+T找到了非终结符,以下同理T ->*F........
(1)找到P->aQ可以找到最后一个终结符
E->E + T
可以找到E的终结符+
T->T * F
可以找到T的终结符*
F -> P↑F
可以找到F的终结符↑
P->(E) | i
可以找到P的终结符 ) 和 i
(2)根据P->aQ(找到递归中的LASTVT(P)
E->T
需要找LASTVT(E),就需要找LASTVT(T)
T-> F
需要找LASTVT(T),就需要找LASTVT(F)
F->P
需要找LASTVT(F),就需要找LASTVT(P)
P -> (E) | i
这里的LASTVT(P)在第一步中已经找到了对应的终结符
(3)第一步加上第二步
LASTVT(E) = {+,*,↑,),i};
LASTVT(T) = {*,↑,),i};
LASTVT(F) = {↑,),i};
LASTVT(P) = {),i};
找到优先表行列位置
根据关系
E -> E + T;
T - > T * F | F
F -> P ↑F | P
P ->(E) | i
这里找关系的话就需要根据
另一个理解来找
对于FIRSTVT(P)的话来说呢...........................................aP
想找到与终结符a的关系就需要找到FIRSTVT(P)
对于LASTVT(P)来说呢...........................................Pa
想要找到与终结符a的关系,就需要找到LASTVT(P)
(至于怎么记忆,文章的最后,我会给出我的理解)
FIRSTVT(P)
想要找到FIRSTVT(P)来确定关系表
首先需要找到每一个(能一眼看出来的)终结符与对应的FIRSTVT(P)的关系,然后按照行去比较
例如
E -> E + T;
找到 + 与FIRSTVT(T)的关系 : a属于FIRSTVT(T)> +
T - > T * F | F
找到 * 与FIRSTVT(F)的关系 : a属于FIRSTVT(F)> *
F -> P ↑F | P
找到 ↑ 与FIRSTVT(F)的关系 : a属于FIRSTVT(F)> ↑
P ->(E) | i
找到 ( 与FIRSTVT(E)的关系 : a属于FIRSTVT(E)> (
FRISTVT(E) = {+,*,↑,(,i};
FIRSTVT(T) = {*,↑,(,i};
FIRSTVT(F) = {↑,(,i};
FIRSTVT(P) = {(,i};
根据这个可以比较出来(注意是比较横排上出现的终结符)
+ | * | ↑ | i | ( | ) | # | |
---|---|---|---|---|---|---|---|
+ | < | < | < | < | |||
* | < | < | < | ||||
↑ | < | < | < | ||||
i | |||||||
( | < | < | < | < | < | ||
) | |||||||
# |
LASTVT(P)
想要找到LASTVT(P)来确定关系表
首先需要找到每一个(能一眼看出来的)终结符与对应的LASTVT(P)的关系,然后按照列去比较
例如
E -> E + T;
找到 + 与LASTVT(E)的关系 : a属于LASTVT(E) > +
T - > T * F | F
找到 * 与LASTVT(T)的关系 : a属于LASTVT(T) > *
F -> P ↑F | P
找到 ↑ 与LASTVT(P)的关系 : a属于LASTVT(P) > ↑
P ->(E) | i
找到 ) 与LASTVT(E)的关系 : a属于LASTVT(E) > )
LASTVT(E) = {+,*,↑,),i};
LASTVT(T) = {*,↑,),i};
LASTVT(F) = {↑,),i};
LASTVT(P) = {),i};
根据这个可以比较出来(注意是比较列排上出现的终结符)
+ | * | ↑ | i | ( | ) | # | |
---|---|---|---|---|---|---|---|
+ | > | > | |||||
* | > | > | > | ||||
↑ | > | > | > | ||||
i | > | > | > | > | |||
( | |||||||
) | > | > | > | > | |||
# |
#E#
最后比较的是#与#的关系
(先写出来)#E可以比较出来a属于FIRSTVT(E) > #
FRISTVT(E) = {+,*,↑,(,i};
(后写出来)E#可以比较出来a属于LASTVT(E) > #
LASTVT(E) = {+,*,↑,),i};
还有两个比较特殊的同一级别的
(),#和#(先)
+ | * | ↑ | i | ( | ) | # | |
---|---|---|---|---|---|---|---|
+ | > | ||||||
* | > | ||||||
↑ | > | ||||||
i | > | ||||||
( | = | ||||||
) | > | ||||||
# | < | < | < | < | < | = |
最后将所有的合并一下,就是所得的结果
+ | * | ↑ | i | ( | ) | # | |
---|---|---|---|---|---|---|---|
+ | > | < | < | < | < | > | > |
* | > | > | < | < | < | > | > |
↑ | > | > | < | < | < | > | > |
i | > | > | > | > | > | ||
( | < | < | < | < | < | = | |
) | > | > | > | > | > | ||
# | < | < | < | < | < | = |
总结
在前文说到了一个方法
可以更好地记忆FIRSTVT和LASTVT的区别
基本概论可以记忆成 FIRSTVT(P) Qa
aQ LASTVT(P)
这样就不会混淆了
在aP和Pa中的比较时
可以理解为 a (FIRSTVT(P) Qa)
(aQ LASTVT(P)) a
这样不管怎么记忆,都是aQa思想