编译原理

编译原理

参考: 【编译原理】期末复习 零基础自学_哔哩哔哩_bilibili第四章 语法分析和语法分析程序_哔哩哔哩_bilibili

易忘的点

句型句子

短语,简单短语(直接短语),句柄

概述,文法,语言

广义推导和多步推导

image-20230404143910056

句型:可以有终结符也可以有非终结符

句子:只有终结符

image-20230404145400493

求闭包:

问题:求短语,简单短语,句柄

image-20230612164049835

先画语法树,再求所有简单短语,找到最左边的简单短语

image-20230612164532176

简单短语也称为直接短语

正规式和有穷自动机

正则式

状态转化图

经常有题目给文法让大伙求状态转移图或者状态转移矩阵:

每行的开头是状态,每列的开头是输入条件

然后逐行书写,看每行的状态指出去的状态就行

image-20230612222634443

DFA

五元组

image-20230629085810570

NFA转DFA (无Σ规则)

先根据NFA写出状态转移图,

再根据上面的图写出一个新的高级的状态转移图,每行的行头是状态集合

image-20230612223208225

然后写一下新的S和F, 就是新的开始状态(初态),F是最终状态(表格元素里含有原来NFA最终状态Z的都是F)

题型:把表达式翻译成三地址代码序列

做法:小学换元,逐行写

文法分析

文法的消除回溯、左递归

消除回溯:

提公因式,提到左边,然后右边整个部分换元A'

然后写A‘->xxx

消除左递归:

形如 A->Aα|β,是存在左递归的,把β提取到最左边,然后A->βA', A'->αA’|伊普西隆

语法分析

自上而下的语法分析

First集

定义:找出最左边所有可能出现的终结符

left -> right

分析first集时,看左边

步骤:求First(A)

1)找到最左边是A的,找到其产生式的最左边字符a,如果是终结符那么a∈First(A)

2)找到最左边是A的,找到其产生式的最左边字符a,如果不是终结符则求First(a), (循环这个步骤直到出现1)

当求First(abcAefg)时,等价于求First(a) 加上 假如abcAefg可以多步推导出空串,就加上空串,看个例题

image-20230621103114781

Follow集

left -> right

分析follow集时,看右边所有出现过目标字符的产生式

步骤:求Follow(A)

image-20230619154429570

0)如果 求Afollow集,A是开始符合,直接#

1)如果 V->xAy, y是终结符,则y∈Follow(A)

2)如果V->xAY, Y是非终结符,则First(Y) ∈ Follow(A)

3)如果V->xAY, Y不管是不是终结符,只要可以多步推导出空串,或者遇到V->xA 这种情况,Follow(V) ∈ Follow(A)

SELECT集

求SELECT

image-20230620164449289

LL(1) / 预测分析表 / 输入串分析过程

  • 判断LL(1)

对于任意两个非终结符A的产生式(比如A->b和A->c)

若 select(A->b) 和 select(A->c) 没有交集,则是LL(1) 文法

  • 消除非LL(1)文法:提取公因子

    image-20230620204316734

提公因式,换元

  • 消除直接左递归

其实相当于把左递归都变成右递归

image-20230620204635936

  • 预测分析表 / 求LL(1)分析表

先写出所有的first集和所有的follow集

(其实只需要写出所有产生式右边字符串ABC的first(ABC))如果遇到空串,则还需要求产生式左边的follow集

根据上面的结果,写LL(1)分析表和字符串栈

image-20230629105342929

举例:

image-20230629105452498

  • 输入串的分析过程

image-20230629162420742

初始化表格

开始符 输入字符

然后一直反序压入栈,直到两个都一样,弹出!

自底向上分析

算符优先分析

算符定义

算符优先文法定义

image-20230620212628562

fitstVT

lastVT

image-20230620214430963

算符优先表

image-20230620221541515

逐条分析即可

求短语,句柄,素短语,

image-20230621095735498

根据算符优先表写栈

LR(0)

1拓展文法

2DFS表

3 action goto表

image-20230621171257967

LR(0)文法的判断:没有冲突项目

假如有冲突项目,可以尝试用下面的SLR(1)文法进行优化

SLR(1)

给定一个文法,如何确定它是SLR(1),并画出相应分析表

步骤:

1.给拓展文法的每个产生式末尾加上#作为终结符,然后求出所有非终结符的follow集

2.写出LR(0)分析表

3.定位到全是rx状态的那行,找到x语句,找到x语句中follow(产生式左边),只保留该follow集中对应的符号的位置,其余擦掉

4.找到有冲突的所有状态,遍历每个状态,看点后面的终结符∩点后面为空的产生式左边的follow集 == {空集} 若为空集则是SLR(1)

(注意,LR(0) ∈ SLR(1) ,理解为完美的无冲突文法,SLR可以理解为优化后无冲突)

找到冲突(就是在一个状态中,一行的点后面跟着空,另外一行的点仍然后面跟着非空)

LR(1)

在LR(0)分析表加上:

1.写出向前搜索符:

文法开始符,就是默认follow(S‘)={#},直接就是写为 S'->S,#

随后,逐行求逗号后面的东西,原则是,先看前面的产生式左边X,再去所有产生式中寻找“点后面是X”的产生式A->.Xy

若y是终结符,则直接把y抄下来

若y是非终结符,求first(y)

若没有这个y,(就是A->.X),直接抄这个产生式逗号后面的字符

2.写出类似于LL(1)表的状态转移图,但是每个状态的向前搜索符都要根据当前状态进行修改!

3.画出action-goto表,但是在写rx的那一行,只填写向前搜索符的地方

image-20230628202101225

注意它标红的这个地方

判断是否是LR(1):

找到冲突的状态,若 点后面的终结符∩点后面为空那一行的向前搜索符==空集

则是LR(1)

根据LR(1)表写出输入串的分析过程:

初始状态

0

#

然后字符串压入符号栈

当字符串栈和状态栈长度不一样时,查表。如果表中对应的情况是某个状态,则把该状态压入状态栈。如果是rx,就归约,归约注意归约掉几个字符就要弹出几个状态。

重复上述过程直至当字符串栈和状态栈长度一样。

一样时,字符串压入/读取输入字符串第一个字符,然后又重复上面过程

一旦状态转移至acc,过程结束

LALR(1)

就是多求一个同心集(产生式相同,向前搜索集不同),把它像下面一样写在一起当作一个状态

这就比较有意思

image-20230628204627418

如何知道LR(0), SLR(1), LR(1) 文法

归约项目:(A->a·) 点后面是空

接受项目:(S->a·) 第一个

移进项目: (S->A·ay) 点后面是终结符

待约项目: (S->A·Ay) 点后面是非终结符

LR(0) 无冲突

SLR(1) 有冲突,

LR(1) 有冲突,向前搜索符∩移进项目终结符 == 空集

LALR(1) 有冲突,可以写同心集

例题

image-20230628222412377

这个只能靠背,LR(1)和SLR(1) 的表的区别是,LR(1)可能两个状态指向同一个rx

给表达式求逆波兰(后缀表示法)

逆波兰:通常把 C=A op B 写成C = AB op的形式,其中等号右边的称为逆波兰式

例题

image-20230629094753016

简单的说就是由外而内的换元,小学换元

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇