编译原理第五章——自下而上分析——LR(1)超详细分析!

本文中内容整理西安交通大学软件学院吴晓军老师的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集~!!)
    • 5.🐼规范规约:LR(k) (最容易考的!!)
    • 6.🐱LALR
  • 五、本章总结

前面部分的链接: 自下而上分析概述算符优先分析LR(0)和SLR详细分析(内含FOLLOW优化构造方法)

5.🐼规范规约:LR(k)

概念
  • 构造问题:有些无二义文法会产生“移进/归约”冲突或“归约/归约”冲突。
  • 产生原因:SLR分析法未包含足够多的“展望”信息。
  • 解决办法:让每个状态含有更多的“展望”信息。
  • 方法:重新定义项目,使得每个项目都附带有k个终结符,即每个项目的形式为:[A->a ⋅ · β, a 1 a 2 ⋯ a k a_1 a_2 \cdots a_k a1a2ak]。
  • 定义:如上形式的项目称为一个LR(k)项目。
  • 说明:
    • 向前搜索符串仅对归约项目[A->a·, a 1 a 2 ⋯ a k a_1 a_2 \cdots a_k a1a2ak]有意义;
    • 归约项目[A->a·, a 1 a 2 ⋯ a k a_1 a_2 \cdots a_k a1a2ak]意味着:当它所属的状态呈现在栈顶且后续的k个输入符号为 a 1 a 2 ⋯ a k a_1 a_2 \cdots a_k a1a2ak时,才可以把栈顶上的a归约为A;
  • 我们只研究k≤1的情形,因为当k = 1的时候已经很很很复杂了,并且已经可以满足绝绝绝大部分需要了~
确定LR(1)项目

确定LR(1)项目的方法:

  • ① 对S和S’,只向前搜索#;
  • ② 其他产生式,对每一个 V t V_t Vt(含#)均向前搜索。

栗子!
(0) S’ -> S
(1) S -> aB
(2) B -> BB
(3) B -> b

由(0)和(1):
S’ -> [·S,#]
S’ -> [S·,#]
S -> [·BB,#]
S -> [B·B,#]
S -> [BB·,#]

由(2)和(3):
B -> [·aB,a]
B -> [·aB,b]
B -> [·aB,#]
B -> [a·B,a]
B -> [a·B,b]
B -> [a·B,#]
B -> [aB·,a]
B -> [aB·,b]
B -> [aB·,#]
B -> [·b,a]
B -> [·b,b]
B -> [·b,#]
B -> [b·,a]
B -> [b·,b]
B -> [b·,#]

是不是写起来很累,对啦,就没打算让你写,这就是让你康康就行的!

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

跟LR(0)分析表的构造一样~

标准步骤:(同样了解即可)

  • 确定LR(1)项目
  • 根据与LR(1)项目构造NFA
  • 利用函数CLOSURE和GO求DFA
  • 根据DFA构造规范LR分析表

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

  • LR(1)项目集规范族的构造
  • LR(1)分析表的构造
LR(1)分析的项目集闭包

假定I是文法G’的任一项目集,定义和构造1的闭包CLOSURE(I)如下:

  • I的任何项目都属于CLOSURE(I)。
  • 若项目[A -> α·Bβ,a]属于CLOSURE(I),B -> ξ \xi ξ是一个产生式,那么,对于FIRST(βa)中的每个终结符b,如果[B -> ξ \xi ξ,b]原来不在CLOSURE(I)中,则把它加进去。
  • 重复执行步骤2,直至CLOSURE(I)不再增大为止。
项目集的转换函数GO

令I是一个项目集,X是一个文法符号,函数GO(I,X)定义为:
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→αX·β,α]的项目| [ A→α٠Xβ, α]∈I} J=任何形如[AαXβ,α]的项目[Aα٠,α]I

直接上例子(重中之重!!)

构造如下拓广文法的规范LR分析表

S -> BB
B -> aB
B -> b

1.为文法编号
(O) S’ -> S
(1) S -> BB
(2) B -> aB
(3) B -> b

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

    1. 先写$ I_0$ = { [S’ -> · S , #] }
    2. 发现 · 后面有非终结符号,写出S的有关项,则$ I_0$ = { [S’ -> · S , #] , [S -> · B B , #]},因为S和S’的项目的搜索符号只有#,自然不必多说。
    3. 发现 · 后面有非终结符号,写出B的有关项,则$ I_0$ = { [S’ -> · S , #] , [S -> · B B , #] , [B -> · a B , ?] , [B -> · b , ?] }
    4. 那么?处到底填什么呢,我们观察[S -> · B B , #]这个项目,当 · 向后移位到第一个B后面时,搜索的就是第二个B了,那么我们填入a/b,则$ I_0$ = { [S’ -> · S , #] , [S -> · B B , #] , [B -> · a B , a/b] , [B -> · b , a/b] }
    5. 至此$ I_0$总算是写完了。
  • 根据$ I_0$可以得到:
    1. $ I_1$ = GO( $ I_0$ , S ) = { [S’ -> S · , #] }
  • 根据$ I_0$可以得到:
    1. $ I_2$ = GO( $ I_0$ , B ) = { [S -> B · B , #] }
    2. 发现 · 后面有非终结符号,写出B的有关项,则$ I_2$ = { [S -> B · B , #] , [B -> · a B , ?] , [B -> · b , ?] }
    3. 那么?处到底填什么呢,我们观察[S -> B · B , #]这个项目,当 · 向后移位到第二个B后面时,搜索的就是#了,那么我们填入#,则$ I_2$ = { [S -> B · B , #] , [B -> · a B , #] , [B -> · b , #] }
  • 根据$ I_0$可以得到:
    1. $ I_3$ = GO( $ I_0$ , a ) = { [B -> a · B , a/b] }
    2. 填入B的有关项,$ I_3$ = { [B -> a · B , a/b] , [B -> · a B , ?] , [B -> · b , ?] }
    3. 我们观察[B -> a · B , a/b]这个项目,当 · 向后移位到B后面时,搜索的是a/b了,所以$ I_3$ = { [B -> a · B , a/b] , [B -> · a B , a/b] , [B -> · b , a/b] }
  • 根据$ I_0$可以得到:
    1. $ I_4$ = GO( $ I_0$ , b ) = { [B -> b · , a/b] }
  • $ I_1$无法进行下一步了,跳~
  • 根据$ I_2$可以得到:
    1. $ I_5$ = GO( $ I_2$ , B ) = { [S -> B B · , #] }
  • 根据$ I_2$可以得到:
    1. $ I_6$ = GO( $ I_2$ , a ) = { [B -> a · B , #] }
    2. 填入B的有关项,$ I_6$ = { [B -> a · B , #] , [B -> · a B , ?] , [B -> · b , ?] }
    3. ? 填入#,$ I_6$ = { [B -> a · B , #] , [B -> · a B , #] , [B -> · b , #] }
  • 根据$ I_2$可以得到:
    1. $ I_7$ = GO( $ I_2$ , b ) = { [B -> b · , #] }
  • 根据$ I_3 可以得到: 可以得到: 可以得到: I_8$ = GO( $ I_3$ , B ) = { [B -> a B · , a/b] }
  • 根据$ I_3$可以得到:GO( $ I_3$ , a ) = $ I_3$
  • 根据$ I_3$可以得到:GO( $ I_3$ , b ) = $ I_4$
  • I 4 I_4 I4无法进行下一步了,跳~
  • I 5 I_5 I5无法进行下一步了,跳~
  • 根据$ I_6 可以得到: 可以得到: 可以得到: I_9$ = GO( $ I_6$ , B ) = { [B -> a B · , #] }
  • 根据$ I_6$可以得到:GO( $ I_6$ , a ) = $ I_6$
  • 根据$ I_6$可以得到:GO( $ I_6$ , b ) = $ I_7$
  • I 7 I_7 I7无法进行下一步了,跳~
  • I 8 I_8 I8无法进行下一步了,跳~
  • I 9 I_9 I9无法进行下一步了,跳~
  • 终于结束辣~~

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

掏出一张空表:

ab#SB
0
1
2
3
4
5
6
7
8
9
  1. 先找acc避免遗忘,[S’ -> S · , #] 在 I 1 I_1 I1:
ab#SB
0
1acc
  1. 按顺序看 I 0 I_0 I0
    • 第一个项目[S’ -> · S , #],点后面是非终结符S,因为$ I_1$ = GO( $ I_0$ , S ),所以输入E前往状态 I 1 I_1 I1,所以GOTO表的第0行第S列写1;
    • 第二个项目[S -> · B B , #],点后面是非终结符B,因为$ I_2$ = GO( $ I_0$ , S ),所以输入E前往状态 I 2 I_2 I2,所以GOTO表的第0行第B列写2;
    • 第三个项目[B -> · a B , a/b],点后面是a,因为$ I_3$ = GO( $ I_0$ , a ),所以输入a以后前往 I 3 I_3 I3,则ACTION表第0行第a列写s3。
    • 第四个项目[B -> · b , a/b],点后面是b,因为$ I_4$ = GO( $ I_0$ , b ),所以输入b后前往 I 4 I_4 I4,则ACTION表第0行第b列写s4。
ab#SB
0s3s412
1acc
  1. 同理往后看 I 1 I_1 I1
    • 哈哈这一行只有一个项目~填过了,过!
  2. 同理往后看 I 2 I_2 I2
    • GOTO表B的位置填5
    • ACTION表a的位置填s6
    • ACTION表b的位置填s7
  3. 同理往后看 I 3 I_3 I3
    • GOTO表B的位置填8
    • ACTION表c的位置填s3
    • ACTION表d的位置填s4
  4. 同理往后看 I 4 I_4 I4
    • 对项目[B -> b · , a/b]可以规约,根据(3)B -> b ,我们在ACTION表的a/b填上r3。
  5. 同理往后看 I 5 I_5 I5
    • 对项目[S -> B B · , #]可以规约,根据(1) S -> BB ,我们在ACTION表的#填上r1。
  6. 同理往后看 I 6 I_6 I6
    • GOTO表B的位置填9
    • ACTION表c的位置填s6
    • ACTION表d的位置填s7
  7. 同理往后看 I 7 I_7 I7
    • 对项目[B -> b · , #]可以规约,根据(3)B -> b ,我们在ACTION表的#填上r3。
  8. 同理往后看 I 8 I_8 I8
  • 对项目[B -> a B · , a/b]可以规约,根据(2) B -> aB ,我们在ACTION表的a/b填上r2。
  1. 同理往后看 I 9 I_9 I9
  • 对项目[B -> a B · , #]可以规约,根据(2) B -> aB ,我们在ACTION表的#填上r2。
ab#SB
0s3s412
1acc
2s6s75
3s3s48
4r3r3
5r1
6s6s79
7r3
8r2r2
9r2

终于,结束辣哈哈哈!!!

6.🐱LALR

概念
  • 问题:对于一般的语言,规范LR分析表要用几千个状态,无法实际应用。
  • 分析:由例6可以看到,有些状态集除了搜索符不同外是两两相同的。
  • 解决办法:合并同心集,构造LALR分析表。

我们称两个LR(1)项目集具有相同的心,如果除去搜索符之后,这两个集合是相同的。

将所有同心的LR(1)项目集合并后,得到一个心就是一个LR(O)项目集。

合并项目集时不用修改转换函数,即GO(1,X);但是,动作ACTION应进行修改,使得能够反映各被合并的集合的既定动作。

合并同心集不会产生新的移进-归约冲突,但有可能产生新的“归约-归约”冲突。

对于同一个文法,LALR分析表和SLR分析表永远具有相同数目的状态,但却能处理一些SLR所不能对付的事情。

构造方法
  • 构造文法G的LR(1)项目集族 C = { I 0 , I 1 , ⋯   , I n } C=\{I_0,I_1,\cdots,I_n\} C={I0,I1,,In}
  • 把所有的同心集合并在一起,记 C ′ = { J 0 , J 1 , ⋯   , J m } C'=\{J_0,J_1,\cdots,J_m\} C={J0,J1,,Jm}为合并后的新族。那个含有项目 [ S ′ → ⋅ S , # ] [S'\to \cdot S,\#] [SS,#] J k J_k Jk为分析表的初态
  • C ′ C' C构造 A C T I O N ACTION ACTION
    • 若项目 [ A → α ⋅ a β , b ] [A\to \alpha \cdot a \beta ,b] [Aαaβ,b]属于 J k J_k Jk G O ( J k , a ) = J i GO(J_k,a)=J_i GO(Jk,a)=Ji a a a为终结符,则置 A C T I O N [ k , a ] ACTION[k,a] ACTION[k,a]为“ s j sj sj
    • 若项目 [ A → α ⋅ , a ] [A\to \alpha \cdot ,a] [Aα,a]属于 J k J_k Jk,则置 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,#]属于 J k J_k Jk,则置 A C T I O N [ k , # ] ACTION[k,\#] ACTION[k,#]为"接受",简记为“ a c c acc acc
  • 构造 G O T O GOTO GOTO
  • 分析表中凡不能用步骤3、4填入信息的空白格均填上“出错标志”
好好好我知道你们都不看,上栗子!

对于刚刚构造的LR(1)项目集规范族,进行同心集合并。

$ I_{36}$ = { [B -> a · B , a/b/#] , [B -> · a B , a/b/#] , [B -> · b , a/b/#] }
$ I_{47}$ = GO( $ I_0$ , a/b/# ) = { [B -> b · , a/b/#] }
$ I_{89}$ = GO( $ I_3$ , a/b/# ) = { [B -> a B · , a/b/#] }

重新写构造表(规则完全一致)。

请添加图片描述

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

五、本章总结

  • 简单来说,这一章是重点中的重点,内容也相当多(看我这1000多行就知道了),相对也比较难理解,当然考的分也很多,就单纯的大题,算符优先分析约10分,LR分析约17分,比前面几章加起来的分都多,所以一定要好好学习~
  • 写题时要注意:看小分写,一般3分对应3个;步骤写全,别偷懒。

我,我的任务完成辣!~~啊哈哈哈哈哈!!(穿山甲的狂笑~)


  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 西安电子科技大学编译原理实验SQL解释器是一个用于解析和执行SQL语句的工具。SQL是一种结构化查询语言,用于管理和操作关系型数据库中的数据。 该解释器的主要功能是将用户输入的SQL语句进行解析和执行。首先,它会将输入的SQL语句进行词法分析,将其划分为不同的单词和符号,并生成一个词法分析树。然后,语法分析器将根据语法规则对词法分析树进行语法分析,生成一个语法分析树。 接下来,解释器会对语法分析树进行语义分析,检查语句是否符合数据库的定义和限制,例如表的存在性、属性的类型和完整性约束等。如果存在错误,解释器会给出相应的错误信息。如果语句通过了语义分析,解释器将根据语义分析树生成对应的查询执行计划。 最后,解释器将执行查询执行计划,从数据库中获取所需的数据,并返回给用户。在执行过程中,解释器会处理各种SQL语句,例如查询语句、更新语句、插入语句等,以及各种子句和操作符,如SELECT、JOIN、WHERE等。 西安电子科技大学编译原理实验SQL解释器的开发需要掌握词法分析、语法分析、语义分析和查询执行等相关知识与技术。它在数据库管理系统中具有重要的应用价值,能够提供方便、高效和准确的数据操作和管理功能,为用户提供了便捷的数据库操作界面。 ### 回答2: 西安电子科技大学编译原理实验中,我们设计了一个SQL解释器。SQL(Structured Query Language)是一种用于管理和处理关系型数据库的编程语言。我们的目标是设计一个能够解析和执行SQL语句的程序。 在我们的实验中,我们首先学习了SQL语言的语法和语义规则,了解了其基本的结构和常用的操作。然后,我们使用编译原理中的词法分析和语法分析技术,对输入的SQL语句进行解析。词法分析阶段将输入的SQL语句拆分为一个个单词(例如关键字、标识符、运算符等),然后语法分析阶段通过对这些单词进行组合和判断,构建SQL语句的抽象语法树。 接下来,我们需要对抽象语法树进行语义分析。通过检查语法树中每个节点的类型和属性,我们可以判断SQL语句在语义上是否合法。例如,我们可以验证表是否存在、列是否匹配、约束是否满足等。如果发现语义错误,我们将在解释器中报告错误信息。 一旦经过语义分析,我们就可以执行SQL语句了。在解释器中,我们根据SQL语句的类型(例如查询、插入、删除、更新等),调用相应的数据库操作,如查询表、插入记录等。我们还可以通过解释器实现一些高级功能,比如支持条件查询、连接查询、聚合函数等。 在实验中,我们还考虑了性能优化。例如,我们可以对SQL语句进行查询优化,选择合适的查询计划来提高查询速度。我们还可以使用缓存来避免重复执行相同的SQL语句。 总的来说,通过实现SQL解释器,我们能够更好地理解和学习编译原理的知识,同时也能够提升对SQL语言的理解和应用能力。通过实验,我们可以更好地掌握SQL语句的解析和执行过程,为未来在数据库设计和开发中更好地使用SQL语言打下基础。 ### 回答3: 西安电子科技大学编译原理 实验中的SQL解释器是一款用于解释和执行SQL语句的程序。SQL(Structured Query Language)是一种用于管理和操作关系数据库的语言,而编译原理是研究如何将高级语言翻译成机器语言的学科。 该SQL解释器的主要功能是接受用户输入的SQL语句,对其进行词法分析、语法分析和语义分析,最终生成并执行相应的数据库操作。 在词法分析过程中,解释器会将输入的SQL语句分解为一个个单词或符号。然后,在语法分析阶段,解释器会根据SQL语法规则,将单词和符号组合成具有语法结构的语句树。接着,在语义分析过程中,解释器会验证语句的语义正确性,并进行必要的类型检查和作用域分析。 完成了上述步骤后,解释器将根据语句树生成相应的数据库操作。这些操作可以包括查询数据、插入记录、更新数据和删除数据等。解释器会调用数据库系统提供的接口,将生成的操作发送给数据库引擎执行,然后将结果返回给用户。 通过实现SQL解释器,我们可以更深入地理解编译原理的相关概念和技术,同时也能够提升对数据库管理系统的理解和应用能力。此外,SQL解释器还可以用于实际开发中,对于处理和管理大量数据的应用程序来说,具有重要的实际意义。 总之,西安电子科技大学编译原理实验中的SQL解释器是一个用于解释和执行SQL语句的程序,它通过词法分析、语法分析和语义分析等步骤,将SQL语句转化为数据库操作,并与数据库引擎进行交互,实现对数据库的操作和管理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值