在自底向下优先分析一章中有一个非常重要的题型——构造优先关系表,接下来我们就来看看具体是怎么操作的。注意:进行这一步的前提是要知道FIRSTVT和LASTVT的求法,大家可以看我之前写的博客:FIRSTVT和LASTVT的计算(很长但是很详细)_驼驼学编程的博客-CSDN博客
1.基本概念
大家可能不太好理解,我们把它转化成伪代码的形式供同学们理解。
2.伪代码呈现
大伙可能看的还是云里雾里,我来和大家解释一下。
给大家举一个例子:P->ABC
我们来看ABC三者的关系,
(1)如果A和C是终结符,B是非终结符,那么A=C
(2)如果A和B都是终结符,A=B
(3)如果A是终结符并且B不是终结符,对于FIRSTVT(B)中的每个元素都>A
(4)如果A是非终结符并且B是终结符,对于LASTVT(A)中的每个元素都>B
3.例题演示
我们已经求得了FIRSTVT和LASTVT
(1)列表:
左边的终结符为横坐标,右边的终结符为纵坐标
(2)求出对应关系并填表:
1.E->E+T|T
对于 E->E+T,我们可以看出‘E+’这个形式符合非终结符+终结符,根据上面的(4),我们可以知道LASTVT(E)的每个元素优先级>+。
我们接着来分析这个式子,'+E'这个形式符合终结符+非终结符,根据上面的 (3),我们可以知道FIRSTVT(E)的优先级<+。
我们再看E->T,不符合上面的结论,跳过。
2.T->T*F|F
推导过程与第一个推导式基本一模一样,只给出推导结果。
3.F->P↑F|P
推导过程与第一个推导式基本一模一样,只给出推导结果。
4.P->(E)|i
这一步与前几步有点不同,我来带大家推导一遍。
’(E)‘可以通过观察可知符合终结符+非终结符+终结符,故符合上面的(1),(=)。
’(E‘与’E)’的推导与上面的过程是一样的。
5.#E#
大家不要忘了这个隐藏的步骤,推导过程与(4)是一样的。
(3)判断是否为算符优先文法
表里无冲突项,是算符优先文法。
附:算符优先文法:
假定G GG是一个不含ϵ \epsilonϵ-产生式的算符文法,对于任何一对终结符a , b a,ba,b,我们说:
a = b a = ba=b,当且仅当文法G GG中含有形如P → … a b … P \rightarrow \dots ab \dotsP→…ab…或P → … a Q b … P \rightarrow \dots aQb \dotsP→…aQb…的产生式;
a < b a < ba<b,当且仅当G GG中含有形如P → … a R … P \rightarrow \dots aR \dotsP→…aR…的产生式,而R ⇒ b … R \Rightarrow b\dotsR⇒b…或R ⇒ Q b … R \Rightarrow Qb\dotsR⇒Qb…;
a > b a > ba>b,当且仅当G GG中含有形如P → … R b … P \rightarrow \dots Rb \dotsP→…Rb…的产生式,而R ⇒ … a R \Rightarrow \dots aR⇒…a或R ⇒ … a Q R \Rightarrow \dots aQR⇒…aQ;
如果一个算符文法G GG中的任何终结符对( a , b ) (a,b)(a,b)至多只满足a = b 、 a < b 、 a > b a = b、a < b、a > ba=b、a<b、a>b这三个关系之一,则称G GG是一个算符优先文法。