程序设计语言-编译原理

算符优先文法构建优先关系表

声明:
本文仅供参考,若有异议,可加评论,我愿积极吸取各位大佬意见

基本思想

算符优先文法

概念:一个文法,如果它的任一产生式的右部都不含有两个相继并列的非终极符,及不含有以下大的格式

.................QR.......................

我们就称该文法为算符文法。

构建两个集合

FIRSTVT(P) 和LASTVT(P)

概念:

FIRSTVT(P) = {a | P\overset{+}{\Rightarrow }a....或 P\overset{+}{\Rightarrow }Qa.......,a\inV_{T}而Q\inV_{N}}

LASTVT(P) = {a | P\overset{+}{\Rightarrow }... 或 P \overset{+}{\Rightarrow }....aQ,a\inV_{T}而Q\inV_{N}}

其中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思想

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值