LR(0)和SLR详细分析(内含FOLLOW优化构造方法)

本文中内容整理西安交通大学软件学院吴晓军老师的ppt中,仅供学习使用,请勿转载或他用
参考教材:《程序设计语言 编译原理》(第3版) 陈火旺等 国防工业出版社

编译原理第五章——自下而上分析


目录

  • 一、复习:语法分析的两种方式
  • 二、自下而上分析概述
    • 1.🐯核心思想:移进-规约
    • 2.🐶规范规约
    • 3.🦁规范规约的两个问题
  • 三、算符优先分析
    • 1.🐸概念辨析-算符文法、算符优先文法
    • 2.🐙概念辨析-算符优先分析法、直观算符优先分析法
    • 3.🐬概念辨析-算符文法、算符优先文法
    • 4.🐳 利用优先关系表用直观算符优先分析法分析算数表达式(不考可以跳过)
    • 5.🐂构造FIRSTVT§和LASTVT§两个集合(必考!!)
    • 6.🐝利用FIRSTVT§和LASTVT§两个集合构造优先关系表(必考!!)
    • 7.🐇素短语
    • 8.🐏优先函数(感觉不会考,至少掌握下概念吧)
  • 四、LR分析法
    • 1.🐡LR分析法概述
    • 2.🍁LR分析过程
    • 3.🐚LR(0) (基础必须掌握!!)
    • 4.🎵SLR (复习一手FOLLOW集~!!)

前面部分的链接: 概述算符优先分析

LR分析法

1.🐡LR分析法概述

LR分析程序框架

请添加图片描述

图片来源于西安交通大学软件工程专业编译原理 吴晓军 2024春
 

核心是总控程序和分析表~

LR分析程序概念
  • LR分析法是一种“移进—归约”的自底向上语法分析方法,其本质是规范归约,具有以下特点:
  • (1) 应用面广:能够用LR分析程序识别绝大多数的程序设计语言的语法结构;
  • (2) 实现效率高:虽构造方法复杂,但是实现(执行)效率高。
  • (3) 查错准确:LR分析器能够及时发现语法错误并准确指出错误位置。
  • LR(k)分析方法中L是指自左(Left)向右扫描输入单词串,R指分析过程是最右(Right)推导的逆过程(规范归约),k是指在决定当前分析动作时需向前察看的输入符号个数。
  • 包括LR(0)、SLR(1)、LR(K)等多种,考试是随机三选一!
LR分析实质:分析栈+DFA

请添加图片描述

图片来源于西安交通大学软件工程专业编译原理 吴晓军 2024春
 
LR分析核心:分析表
  • 分析表由ACTION表和GOTO表两部分组成。
  • ACTION(s, a):表示当状态s面临输入a时的动作;
  • GOTO(s,x):表示面对文法符号x的下一状态。
  • ACTION(s, a)的动作种类:
    • 移进s:(shift)
    • 规约r:(reduction)
    • 结束acc
    • 报错(空格)

例子,下面的文法的构造表如下:
文法必须有编号
(1) E -> E + T
(2) E -> T
(3) T -> T * F
(4) T -> F
(5) F -> ( E )
(6) F -> i

i+*()#ETF
0s5s4123
1s6acc
2r2s7r2r2
3r4r4r4r4
4s5s4823
5r6r6r6r6
6s5s493
7s5s410
8s6s11
9r1s7r1r1
10r3r3r3r3
11r5r5r5r5
LR文法
  • LR分析法是针对LR文法的。
  • 对于一个文法,如果能构造出一个分析表,使得每个入口都是唯一确定的,那他就是LR文法。
  • LR(k)文法的k是指在决定当前分析动作时需向前察看的输入符号个数。
  • LR文法绝不会有二义性,也就是说,绝不会发生移进与规约冲突规约与规约冲突

2.🍁LR分析过程

请添加图片描述

图片来源于西安交通大学软件工程专业编译原理 吴晓军 2024春
 
例:利用上述分析表,假定输入串为 i*i+i,描述LR分析器的工作过程

这里不再给出完整过程,不是重点。

状态符号输入串
00#i*i+i#
105#i*i+i#
203#F*i+i#
3
  • 第0步到第1步:表中是s5,则读入5和i;
  • 第1步到第2步:
    • 表中是r6,根据第6个产生式化简,符号变成#F,状态变成06
    • GOTO表对应了3,状态变成03

3.🐚LR(0)

LR(0)分析表的构造步骤

标准步骤:(了解即可

  1. 确定G的LR(0)项目
  2. 以LR(0)项目为状态,构造一个能识别文法G的所有活前缀的NFA
  3. 利用子集法将NFA确定化,成为以项目集合为状态的DFA
  4. 根据上述DFA可直接构造出LR(0)分析表

简化步骤:(也是考试的步骤)

  1. LR(0)项目集规范族的构造
  2. LR(0)分析表的构造
LR(0)项目
  • LR(0)项目简称为项目
  • 定义:文法G的每一个产生式的右部添加一个圆点,称为G的一个LR(0)项目
  • 项目的意义:指明在分析过程的某时刻我们看到产生式多大一部分
  • 项目在计算机中的表示:(m, n)
  • m代表产生式编号
  • n指出圆点的位置
  • 例子:对于A -> XY有三个项目,分别是A -> ⋅ · XY , A -> X ⋅ · Y , A -> XY ⋅ ·
  • 但是对于A -> ϵ \epsilon ϵ空字,只有一个项目A -> ⋅ ·
前缀、活前缀
  • 前缀指该字的任意首部
  • 如:abc的前缀包括 ε , a , a b , a b c \varepsilon,a,ab,abc ε,a,ab,abc
  • 活前缀:规范句型的一个前缀,该前缀不含句柄之后的任何符号。
  • 活前缀包含的句柄并不完整,完整了就会直接规约了
利用CLOSURE方法构造LR(0)项目集规范族
  • 拓广文法
  • C L O S U R E ( I ) CLOSURE(I) CLOSURE(I)算法(其中 I I I G G G的任一项目集)
    • I的任何项目都属于 C L O S U R E ( I ) CLOSURE(I) CLOSURE(I)
    • A → α ⋅ B β A\to \alpha \cdot B \beta Aα属于 C L O S U R E ( I ) CLOSURE(I) CLOSURE(I),那么,对任何关于B的产生式 B → γ B\to \gamma Bγ,项目 B → ⋅ γ B\to \cdot \gamma Bγ也属于 C L O S U R E ( I ) CLOSURE(I) CLOSURE(I)
    • 重复执行上述两步骤直至 C L O S U R E ( I ) CLOSURE(I) CLOSURE(I)不再增大为止
  • 构造项目集规范族的方法
    • 令NFA的初态为 I I I,求其 C L O S U R E ( I ) CLOSURE(I) CLOSURE(I),得到初态项目集。即:求 C L O S U R E ( { S ′ → ⋅ S } ) CLOSURE(\{S'\to \cdot S\}) CLOSURE({SS})
    • 对所得项目集 I I I和文法 G G G的每个文法符号 X X X(包括 V T 和 V N V_T和V_N VTVN)计算 G O ( I , X ) = C L O S U R E ( J ) GO(I, X)=CLOSURE(J) GO(I,X)=CLOSURE(J),得到新的项目集,其中: J = { 任何形如 A → α X ⋅ β 的项目 ∣ A → α ⋅ X β 属于 I } J=\{任何形如A\to \alpha X\cdot \beta的项目|A\to \alpha \cdot X \beta属于I\} J={任何形如AαXβ的项目Aα属于I}
    • 重复步骤二,直至没有新的项目集出现
LR(0)分析表的构造
  • 若项目 A → α ⋅ a β A\to \alpha \cdot a\beta Aαaβ属于 I k I_k Ik G O ( I k , a ) = I j GO(I_k,a)=I_j GO(Ik,a)=Ij a a a为终结符,则置 A C T I O N [ k , a ] ACTION[k, a] ACTION[k,a]为“把 ( j , a ) 移进栈 (j,a)移进栈 (j,a)移进栈”,简记为“ s j sj sj
  • 若项目 A → α ⋅ A\to \alpha \cdot Aα属于 I k I_k Ik,那么,对任何输入符号 a a a(或者终结符#)置 A C T I O N [ k , a ] ACTION[k,a] ACTION[k,a]为"用产生式 A → α A\to \alpha Aα进行归约",简记为" r j rj rj":其中,假定 A → α A\to \alpha Aα为文法 G ’ G’ G的第 j j j个产生式
  • 若项目 S ′ → S ⋅ S'\to S\cdot SS属于 I k I_k Ik,则置 A C T I O N [ k . # ] ACTION[k.\#] ACTION[k.#]为”接受“,简记为" a c c acc acc"
  • G O ( I k , A ) = I j , A GO(I_k,A)=I_j,A GO(Ik,A)=Ij,A为非终结符,则置 G O T O [ k , A ] = j GOTO[k,A]=j GOTO[k,A]=j
  • 分析表中凡不能使用规则1至4填入信息的空白格均置上“出错标志”
不扯淡了直接上例子反正定义也看不懂😅😅

对于文法G:

S’ -> E
E -> a A | b B
A -> c A | d
B -> c B | d
利用CLOSURE方法构造LR(0)项目集规范族,并且构造LR(0)分析表

1.为文法编号
(0)S’ -> E
(1)E -> a A
(2)E -> b B
(3)A -> c A
(4)A -> d
(5)B -> c B
(6)B -> d

2.利用CLOSURE方法构造LR(0)项目集规范族

先得到$ I_0$ ={ $S’ -> · E , E -> · a A , E -> · b B $ }

根据$ I_0$可以得到:
$ I_1$ = GO( $ I_0$ , E ) = { S ’ − > E ⋅ S’ -> E · S>E }
$ I_2$ = GO( $ I_0$ , a ) = { $E -> a · A , A -> · c A , A -> · d $ }
$ I_3$ = GO( $ I_0$ , b ) = { $E -> b · B , B -> · c B , B -> · d $ }

$ I_1 无法进行下一步了,跳 同理根据 无法进行下一步了,跳~ 同理根据 无法进行下一步了,跳 同理根据 I_2$可以得到:
$ I_4$ = GO( $ I_2$ , A ) = { E − > a A ⋅ E -> a A · E>aA }
$ I_5$ = GO( $ I_2$ , c ) = { $A -> c · A , A -> · c A , A -> · d $ }
$ I_6$ = GO( $ I_2$ , d ) = { $A -> d · $ }

同理根据$ I_3$可以得到:
$ I_7$ = GO( $ I_3$ , B ) = { E − > b B ⋅ E -> b B · E>bB }
$ I_8$ = GO( $ I_3$ , c ) = { $B -> c · B , B -> · c B , B -> · d $ }
$ I_9$ = GO( $ I_3$ , d ) = { $B -> d · $ }

$ I_4 无法进行下一步了,跳 同理根据 无法进行下一步了,跳~ 同理根据 无法进行下一步了,跳 同理根据 I_5$可以得到:
$ I_{10}$ = GO( $ I_5$ , A ) = { A − > c A ⋅ A -> c A · A>cA },没有重复
GO( $ I_5$ , c ) = { $A -> c · A , A -> · c A , A -> · d $ } = $ I_{5}$
GO( $ I_5$ , d ) = { $A -> d · $ } = $ I_{6}$

$ I_6$无法进行下一步了,跳~
$ I_7$无法进行下一步了,跳~
$ I_8$ 分析和$ I_5$类似
$ I_{11}$ = GO( $ I_8$ , B ) = { B − > c B ⋅ B -> c B · B>cB },没有重复
GO( $ I_8$ , c ) = { $B -> c · B , B -> · c B , B -> · d $ } = $ I_{8}$
GO( $ I_8$ , d ) = { $B -> d · $ } = $ I_{9}$

$ I_9$无法进行下一步了,跳~
$ I_{10}$无法进行下一步了,跳~
$ I_{11}$无法进行下一步了,跳~
分析结束~~

3.利用LR(0)项目集规范族构造LR(0)分析表

掏出一张空表:

abcd#EAB
0
1
2
3
4
5
6
7
8
9
10
11
  1. 先找acc避免遗忘, S ’ − > E ⋅ S’ -> E · S>E I 1 I_1 I1:
abcd#EAB
0
1acc
2
  1. 按顺序看 I 0 I_0 I0
    • 第一个项目 S ’ − > ⋅ E S’ -> · E S>E,点后面是非终结符E,因为$ I_1$ = GO( $ I_0$ , E ),所以输入E前往状态 I 1 I_1 I1,所以GOTO表的第0行第E列写1;
    • 第二个项目$ E -> · a A ,点后面是 a ,因为 ,点后面是a,因为 ,点后面是a,因为 I_2$ = GO( $ I_0$ , a ),所以输入a以后前往 I 2 I_2 I2,则ACTION表第0行第a列写s2。
    • 第三个项目$ E -> · b B ,点后面是 b ,因为 ,点后面是b,因为 ,点后面是b,因为 I_3$ = GO( $ I_0$ , b ),所以输入b后前往 I 3 I_3 I3,则ACTION表第0行第b列写s3。
abcd#EAB
0s2s31
1acc
2
3
  1. 同理往后看 I 1 I_1 I1
    • 哈哈这一行只有一个项目~填过了,过!
  2. 同理往后看 I 2 I_2 I2
    • GOTO表A的位置填4
    • ACTION表c的位置填s5
    • ACTION表d的位置填s6
  3. 同理往后看 I 3 I_3 I3
    • GOTO表B的位置填7
    • ACTION表c的位置填s8
    • ACTION表d的位置填s9
abcd#EAB
0s2s31
1acc
2s5s64
3s8s97
  1. 同理往后看 I 4 I_4 I4
    • 对项目 E − > a A ⋅ E -> a A · E>aA,A可以规约,根据(1)E -> a A ,我们在ACTION表上都填上r1。
abcd#EAB
0s2s31
1acc
2s5s64
3s8s97
4r1r1r1r1r1
  1. 同理往后看 I 5 I_5 I5
    • GOTO表A的位置填10
    • ACTION表c的位置填s5
    • ACTION表d的位置填s6
  2. 同理往后看 I 6 I_6 I6
    • (4)A -> d ,我们在ACTION表上都填上r4。
  3. 同理往后看 I 7 I_7 I7
    • (2)E -> b B,我们在ACTION表上都填上r2。
  4. 同理往后看 I 8 I_8 I8
  • GOTO表B的位置填11
  • ACTION表c的位置填s8
  • ACTION表d的位置填s9
  1. 同理往后看 I 9 I_9 I9
  • (6)B -> d ,我们在ACTION表上都填上r6。
  1. 同理往后看 I 10 I_{10} I10
  • (3)A -> c A ,我们在ACTION表上都填上r3。
  1. 同理往后看 I 11 I_{11} I11
  • (5)B -> c B,我们在ACTION表上都填上r5。
abcd#EAB
0s2s31
1acc
2s5s64
3s8s97
4r1r1r1r1r1
5s5s610
6r4r4r4r4r4
7r2r2r2r2r2
8s8s911
9r6r6r6r6r6
10r3r3r3r3r3
11r5r5r5r5r5

LR(0)最显著的特征:ACTION表规约的行是相同的。

4.🎵SLR

概念
  • SLR的S是simple的意思~
  • 与LR(0)相比的优缺点:
  • 优点:可以处理更多种类的文法,毕竟LR(0)能处理的文法实在有限。
  • 缺点:稍微难构造一点,可以处理的文法更多了但又没那么多~
构造方法
  • 跟LR(0)非常类似,只有一点不同,在根据项目集规范族构造分析表的时候,对于规约的操作,要向前展望,看一下FOLLOW集。
  • 必须掌握FIRST集和FOLLOW集的构建!
  • 上栗子!!别慌,先回忆下FOLLOW集求法,待会得用。
FOLLOW集

求FOLLOW集合的意思就是求非终结符右边所有终结符的集合。

E -> TE’
E’ -> +TE’ | ε
T -> FT’
T’ -> *FT’ | ε
F -> (E) | id

求FOLLOW集的绝家秘法!!!

  1. 将#放到FOLLOW(S)中,其中S是文法的开始符号。
  2. 从上向下扫描每一个文法式子,对于右边的每一个非终结符:
    • 把所有跟在非终结符后面的终结符加入对应的FOLLOW集合(F -> (E),把)加入E的FOLLOW集合);
    • 对于所有跟在非终结符后面的非终结符号(T -> FT’,直接把T’的FIRST集合中的元素(除了ε)加入F的FOLLOW集合)
    • 这一步只需要执行一次,并且完全不用考虑式子的左半部分。
    • 我们关注式子的右半部分,关注每一个非终结符。
  3. 从上向下扫描每一个文法式子,对于右边的每一个非终结符:
    • 对于末尾的非终结符(E -> TE’的E’),直接把FOLLOW(E)加入FOLLOW(E’);
    • 对于非末尾的非终结符(E -> TE’的T),考察FIRST(E’)是否包含ε,如果包含那么也把FOLLOW(E)加入FOLLOW(T)。
    • 这一步需要执行多次,最好进行检验。
    • 我们需要关注右边的每一个非终结符。
上栗子

前面完全和LR(0)一致,直到开始在表中写r开始变得不同~

abcd#EAB
0s2s31
1acc
2s5s64
3s8s97

LR(0)当初是这样写的:

  1. 同理往后看 I 4 I_4 I4
    • 对项目$E -> a A ·
      $,A可以规约,根据(1)E -> a A ,我们在ACTION表上都填上r1。

所以:

abcd#EAB
0s2s31
1acc
2s5s64
3s8s97
4r1r1r1r1r1

SLR的话我们这样改:

  1. 同理往后看 I 4 I_4 I4
    • 对项目$E -> a A ·
      $,A可以规约,根据(1)E -> a A ,我们查看FOLLOW(E)集合,发现只有一个#,那么我们就只在#列填r1
abcd#EAB
0s2s31
1acc
2s5s64
3s8s97
4r1
  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值