编译原理复习

本文深入探讨了程序设计语言的语法描述,包括语法树、自上而下的语法分析、LL1文法、回溯解决、预测分析表构造、自下而上的语法分析。讲解了消除左递归、提取左因子、LL(1)文法、SLR分析等关键技术,并通过实例展示了分析过程。此外,还提到了词法分析、中间代码生成以及语义分析在编译过程中的作用。

第三章 程序设计语言的语法描述

1.语法树

第四章 自上而下的语法分析

语法分析:根据给定的语法定义,判断输入的句子是否符合语法规则,识别句子并确定句子类型;
自上而下语法分析步骤:
(1)消除歧义:无二义性
(2)文法改造:消除左递归;提取左因子
(3)文法判定:LL1文法,文法确定性

直接左递归:含有A->Aa形式产生式的文法;
若一个文法中有一个非终结符A使得对某个串a存在一个推倒A=>+Aa,那么这个文法就是左递归的;
经过两步或以上推导产生的左递归称为间接左递归;
消除左递归:
S->Sa|b
=>
S→bS’
S’→aS’|ε

e.g.
E->E+T|T
T->T*F|F
F->(E)|i|x|y
=>
E->TE’
E’->+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|i|x|y

直接左递归消除一般规则:
P→Pα1|Pα2|…|Pαm|β1|β2|…|βn
=>
P→β1P’|β2P’|…|βnP’
P’→α1P’|α2 P’|…|αm P’ |ε
e.g.
A → A c | A a d | b d | ε
=>
A->bdA’|A’
A’->cA’|adA’|ε
产生回溯的原因:
(1)多个候选式右部第一个符号相同
e.g.S->ab|ac S->Aa|Ab
解决:提取左因子
(2)多个右部其中一个可以退出ε
e.g.S->Ba B->a|ε
解决:要去描述语言符合LL1文法

提取左因子:
e.g. N-> DN|D
D->0|1|2|3|4|5|6|7|8|9
=>
N->D(N|ε)
=>
N->DN’
N’->N|ε
D->0|1|2|3|4|5|6|7|8|9

S-> aAd|aBe
A->c
B->b
=>
S->aS’
S’->Ad|Be
A->c
B->b

提取左因子一般规则:
P→δβ1|δβ2|…|δβn,δ∈(VT∪VN)+,βi∈(VT∪VN)*
=>
P→δP’
P’→β1|β2|…|βn

4.5.回溯的解决 -LL(1)文法
follow集:
e.g. E->TE’, 则follow(E’)应该添加Follow(E);
若E’可以为空串,则follow(T)应添加follow(E);
first集:
e.g.E->TE’,则first(E)应添加first(T)
若T可以为空串,则first(E)应添加first(E’)

select集
A->al
若空串不属于first(a), 则SELECT(A->a) = first(a)
若空串属于first(a), 则SELECT(A->a) = (first(a) - {空串})Vfollow(a)

文法G为LL1文法,当且仅当G的任意两个具有相同左部的产生式A->a|b满足下面条件:
不存在终结符a使得a和b都能够推导出以a开头的串
a和b至多有一个能推导出空串;
select(A->a)交select(A->b) = 空串;
设文法G:
A->aB|d
B->bBA|空串
=>
first(A)={a,d,#} follow(A) = {a,d,#};
first(B) = {b} follow(B) = {a,d,#}

	select(A->aB)交select(A->d) = 空集
	select(B->bBA)交select(B->空串) = 空集

递归下降分析法:

E->TE’
E’->+TE’|空串
T->FT’
T’->*FT’|空串
F->(E)|i|x|y
=>
(a+b)*c
(i+i)*c#

step调用过程code输入串
0E(a+b)*c
1TE’(a+b)*c
2FT’E’(a+b)*c
3E)T’E’ii+i)*i
4TE’)T’E’ii+i)*i
5FT’E’)T’E’ii+i)*i
6T’E’)T’E’+i)*i
7E’)T’E’+i)*i
8TE’)T’E’i)*i
9FT’E’)T’E’i)*i
10T’E’)T’E’)*i
11E’)T’E’)*i
12T’E’*i
13FT’E’i#
14T’E’#
15E’#
16#

分析表构造法:
(1)构造所有候选式的first集,构造所有非终结符的follow集
(2)对于文法的每个产生式A->a执行3和4
(3)对于a∈first(α) ,将A->a加到M[A][a]
(4)若ε∈first(α),则对于每个终结符b∈follow(A),把A→ε加至M[A][b]。
e.g.
E->TE’
E’->+TE’
E’->空串
T->FT’
T’->*FT’
T’->空串
F->(E)
F->i
F->x
F->y
=>
first(E)={(,i,x,y} follow(E)={),#}
first(E’)={+,空串,} follow(E’)={),#}
first(T)={(,i,x,y} follow(T)={+,),#}
first(T’)={空串,*} follow(T’)={+,),#}
first(F)={(,i,x,y,} follow(F)={*,+,),#}

构造预测分析表:

+*()ixy#
EE->TE’E->TE’E->TE’E->TE’
E’E’->+TE’E’->空串E’->空串
TT->FT’T->FT’T->FT’T->FT’
T’T’->空串T’->*FT’T’->空串T’->空串
FF->(E)F->iF->xF->y

e.g.i+i#

stepstackXcode输入串
0#Ei+i#
1E’Ti+i#
2E’T’Fi+i#
3E’T’ii+i#
4E’T’+i#
5E’+i#
6E’T++i#
7E’Ti#
8E’T’Fi#
9E’T’ii#
10E’T’##
11E’#
12#

1.预测分析法是由分析表和控制程序构成,控制程序与文明发无关,分析表随文法而异;
2.在预测分析表中,若某一单元持有一个或以上的产生式,则称该预测分析表含多重定义;
3.一个文法,若其预测分析表不存在多重定义,则称该文法为LL(1)文法,即 对于A->a|b, first(a)交first(b) = {};若b->空串,则first(a)交follow(A)={};

预测分析表二义性:
e.g.
S->fCtS|fCtSeS|a
C->i
=>
S->fCtSS’|a
S’->空串|eS
C->i

first(S) = {f,a} follow(S)={e,#}
first(S’)={空串,e} follow(S’)={e,#}
first©={i}

ftaei#
SS->fCtSS’S->a
S’S’->eS/S’->空串S’->空串
CC->i

输入:fitaea

stepstackcode输入串
0#Sfitaea
1#S’StCffitaea
2#S’StCitaea
3#S’Stiitaea
4#S’Sttaea
5#S’Saea
6#S’aaea
7#S’ea
8此处有歧义

第五章 自下而上的语法分析

从叶节点出发,步步向上规约。若能规约到根节点,说明输入串合法
移入:将输入符号移到栈的顶端
规约:
接受:Acc,语法分析成功
抛错:语法分析抛错
e.g.产生式
	1.S→aAcBe
	2.A→b
	3.A→Ab
	4.B→d 
step符号栈剩余输入动作
0$abbcde$
1$abbcde$移入
2$abbcde$移入
3$aAbcde$规约
4.$aAbbcde$移入
5$aAbcde$规约
6$aAbcde$移入
7$aAcde$规约
8$aAcde$移入
9$aAcde$移入
10$aAcBe$规约
11$aAcBe$移入
12$S$规约
短语:子树端末结点的自左至右的排列,称为相对于子树根的短语;

在这里插入图片描述
短语:b bb d
直接短语:Ab Bd
句柄:Ab

直接短语(简单短语):两代子树端末结点的自左至右的排列,称为相对于两代子树根的直接短语;

句柄:最左面的两代子树的端末结点的自左自右的排列;

  1. 句型:语法树端末结点的自左自右的排列;(规约过程中产生的值)
  2. 句子:语法树端末结点的自左自右的排列,且端末结点均为终结符;
  3. 短语:子树端末结点自左自右的排列,称为相对于子树根的短语;
  4. 直接短语:两代子树端末结点的自左自右的排列;
  5. 句柄:最左面的两代子树的端末结点的自左至右的排列;(给我感觉像是产生式右侧的值)

规范规约(最左规约):
设a是文法G的一个句子,并且序列an,an-1,…a0满足下列三个条件,称该序列是a的一个规范规约。
(1)an = a
(2)a0 = S
(3)ai-1是将ai中的句柄替换成产生式的做不夫哈而得到的 (1<=i<=n)

前缀: 符号串的任意首部;e.g.a=abc 前缀有空串, a, ab, abc
活前缀:规范句型的一个前缀,不包括句柄后的任何符号。
a = aAbcde, 因为Ab是该句型的句柄,所以该句型的活前缀有空串,a, aA, aAb

LR分析法:LR分析法严格执行最左规约,每次按句柄规约。LR分析法把句柄的识别过程划分为若干状态,每个状态仅识别句柄的一个符号,若干个状态就可识别句柄的一部分左端符号。识别了句柄这一部分就相当于识别规范句型的左起部分,即活前缀。这样,对句柄的识别就变成了对活前缀的识别,可以构造一个DFA,用于识别给定文法所有贵方句型的活前缀;
增广文法:在G中加上新开始符号 S’ -> S 而得到的文法,引入该产生式的目的是使得文法开始福海仅出现在一个产生式左边,从而使得分析器仅有一个接受状态;

项目集I的闭包(CLOSURE(I)),就是把.后面的所有项目加上
在这里插入图片描述
e.g.
(0)S'->S(1)S->BB(2)B->aB(3)B->b

stateab#SB
0S4S123
1r3r3r3
2Acc
3S4S15
4S4S16
5r1r1r1
6r2r2r2

若一个项目集既含有移进项目,又含有一个或多个规约项目,则称该LR(0)项目集含有冲突项目,冲突项目使得分析表含有多重定义入口。
LR(0):若构造的分析鞭炮不含多重定义入口,则称该分析表是LR(0)分析表,相应文法为LR(0)文法;

SLR(1): 若t.code和b相等,则移进输入符号;
若t.code属于follow(A),则使用产生式 A->a进行规约;
若t.code属于follow(B),则使用产生式B->a进行规约;

SLR(1)是LR(0)的扩展,
(1)引入增广文法 S’->S
(2)对所有产生式进行编号
(3)构造文法其DFA
(4)计算follow集

在这里插入图片描述

stepstatestringvalwvalcurrent
0#--<i,‘a’>
0 5#i-a<*,nil>
0 3#F-&a<*,nil>
0 2#T-&a<*,nil>
0 2 7#T*&a–<i,‘b’>
0 2 7 5#T*i—b-&a–<+,nil>
0 2 7 10#T*F-----&a-&b<+,nil>
0 2#T-&T1<+,nil>(*,&a,&b,&T1)
0 1#E-&T1<+,nil>
0 1 6#E+-&T1-<i,‘c’>
0 1 6 5#E+i—c-&T1–<#,nil>
0 1 6 3#E+F-----&T1-&c<#,nil>
0 1 6 9#E+T-----&T1-&c<#,nil>
0 1#E-&T2<#,nil>(+,&T1,&c,&T2)
Acc

(1)LR分析表
(2)状态栈:设置状态栈,用于记录分析过程中所经历的状态,即路径
(3)符号栈:用于记录路径的符号,其和状态栈等高
(4)产生式右部符号串长度:因每个状态仅识别一个符号,退回的状态数和构成句柄的字符数相等,因此需要存储产生式右部符号串长度。
(5)产生式左部符号:规约后,根据左部符号进入下一状态

第六章

1.词法分析

词法分析器,依据语言的构词规则。从文件读入源程序,由字符拼接单词
e.g.

类别:值
3+abc*128
('x',"3")
('+',)
('i',"abc")
('*',)
('x',128)

=》
x+i*x

2.语法分析

根据语言的语法规则,将词法分析器所提供的单词种别分成各类语法范畴。

3.中间代码生成

中间代码的生成有时称为语义分析,执行中间代码产生的程序称为中间代码产生器=》按照语法分析器所识别出的语法范畴产生相应的中间代码,并建立符号表,常数表等各种表格

4.目标代码生成(后端)

依据中间代码和表格信息,确定各类数据在内存中的位置,选择合适的指令代码,将中间代码翻译成汇编语言或机器指令,这部分工作与硬件有关。

第二章 词法分析

从文件读入源程序,由字符拼接单词。每当识别出一个单词,就产生这个单词的内部码。
基本字(real),标识符(),常数,运算符,界符(;,)
经过词法分析后,单词使用二元式来表示,code表示单词的种别,表示单词的语法特性,val表示单词的值,表示单词的语义特性
e.g.
输入

	begin
		real r,h,s;
		s = 2*3.14*r*(r+h)
	end
('{',"null")
('c',"null")
('i',"r")
(',',"null")
('I',"h")
(',',"null")
('i',"s")
(';',"null")
('i',"s")
('=',"null")
('x',"2")
('*',null")
('y',"3.14")
('*',"null")
('i',"r")
('*',"null")
('(',"null")
('i',“r”)
('+',"null")
('i',"h")
(')',"null")
('}',"null")

第6章 语法制导翻译和中间代码生成

1.语法分析:利用产生式推导或规约,验证符号串是否为文法的一个句子
2.语义分析:规定每个符号和符号串的意义,同时完成符号串所规定的语义动作;
(1)建立符号表和常数表
(2)诊断和报告源程序中的语义错误
(3)根据语言的语义产生中间代码,或直接解释执行

  1. SLR分析器由工作栈(状态栈,符号栈),分析表和总控程序三部分组成

状态栈
PS:
(1)在移进时,除移进状态和单词的种别外,还需移进单词的值;
(2)在用某个产生式进行规约时,除需执行规约动作外,还需调用相应语义子程序;

e.g.
解释执行
(1)文法及语义子程序
(2)SLR分析表
(3)手工计算
在这里插入图片描述
e.g.
7+9*5

1.分析二元式
<x,‘7’>
<+,nil>
<x,‘9’>
<*,nil>
<x,‘5’>
<#,nil>

stepstatestringword_valvalcurrent
00#--<x,‘7’>
10 3#x-7<+,nil>
20 1#E- -- &7
30 1 4#E+-&7-<x,‘9’>
40 1 4 3#E+x—9-&7–<*,nil>
50 1 4 7#E+E-----&7-&9
60 1 4 7 5#E+E*------&7-&9-<x,‘5’>
70 1 4 7 5 3#E+E*x-----5-&7-&9–<#,nil>
80 1 4 7 5 8#E+E*E-------&7-&9-&5<#,nil>
90 1 4 7#E+E-----&7-&45<#,nil>,(*,&9,&5,&T1)
100 1#E-&52<#,nil>,(+,&7,&T1,&T2)
110 1#EAcc

结束

e.g.
在这里插入图片描述

0.S’->S
1.S->i=X
2.X->X+Y
3.X->Y
4.Y->Y*Z
5.Y->Z
6.Z->(X)
7.Z->-Z
8.Z->i
9.Z->x

follow(S) ={#};
follow(X) = {+,#,)};
folow(Y) = {,+,#,),}
follow(Z) = {
,+,#,)};//r8

ix+*-=()#XYZS
0S21
1Acc
2S8
3S9r1
4r3S10r3r3
5S12S7S6S511418
6S12S7S6S517
7r9r9r9r9
8S12S7S6S513418
9S12S7S6S51418
10S12S7S6S515
11S9S16
12r8r8r8r8
13S9r1
14r2S10r2r2
15r4r4r4r4
16r6r6r6r6
17r7r7r7r7
18r5r5r5r5

//分析

a=-b*(c+2)
<i,‘a’>
<=,nil>
<-,nil>
<i,‘b’>
<*,nil>
<(,nil>
<i,‘c’>
<+,nil>
<x,2>
<),nil>
<#,nil>

stepstatestringword_valvalcurrent
0#--<i,‘a’>
0 2#i-a<=,nil>
0 2 8#i=-a-<-,nil>
0 2 8 6#i=--a–----<i,‘b’>
0 2 8 6 12#i=-i-a–b-----<*,nil>
0 2 8 6 17#i=-Z-a—----&b<*,nil>
0 2 8 18#i=Z-a–—&T1<*,nil>,(-,&b,nil,&T1)
0 2 8 4#i=Y-a–—&T1<*,nil>
0 2 8 4 10#i=Y*-a——&T1-<(,nil>
0 2 8 4 10 5#i=Y*(-a----—&T1–<i,‘c’>
0 2 8 4 10 5 12#i=Y*(i-a----c----&T1—<+,nil>
0 2 8 4 10 5 18#i=Y*(Z-a-----—&T1–&c<+,nil>
0 2 8 4 10 5 4#i=Y*(Y-a-----—&T1–&c<+,nil>
0 2 8 4 10 5 11#i=Y*(X-a-----—&T1–&c<+,nil>
0 2 8 4 10 5 11 9#i=Y*(X+-a-----—&T1–&c-<x,2>
0 2 8 4 10 5 11 9 7#i=Y*(X+x-a-----2—&T1–&c-<),nil>
0 2 8 4 10 5 11 9 18#i=Y*(X+Z-a------—&T1–&c-&2<),nil>
0 2 8 4 10 5 11 9 14#I=Y*(X+Y-a------—&T1–&c-&2<),nil>
0 2 8 4 10 5 11#i=Y*(X-a-----—&T1–&T2<),nil>(+,&c,&2,&T2)
0 2 8 4 10 5 11 16#i=Y*(X)-a------—&T1–&T2-<#,nil>
0 2 8 4 10 15#i=Y*Z-a----—&T1-&T2<#,nil>
0 2 8 4#i=Y-a–—&T3<#,nil>(*,&T1,&T2,&T3)
0 2 8 13#i=X-a–—&T3<#,nil>
0 1#S-&T4<#,nil>(=,&T3,0,&i )
Acc

6.7.布尔表达式的翻译
(1)控制语句的条件 if x+y<10 goto L
(2)计算逻辑值 d = x>y

if(a){
	X+1
}else{
	x-1
}
//other

(1)(jnz,&a,0,3)
(2)(jmp,0,0,5)
(3)(+,&x,&1,&T1)
(4)(jmp,0,0,other)
(5)(-,&x,&1,&T2)
(6)other

if aVbVc the x+1 else x-1
(1)(jnz,&a,0,7)
(2)(jmp,0,0,3)
(3)(jnz,&b,0,7)
(4)(jmp,0,0,_5)
(5)(jnz,&c,0,7)
(6)(jmp,0,0,9)
(7)(+,&x,&1,&T1)
(8)(jmp,0,0,10)
(9)(-,&x,&1,&T2)
(10)other


if a&b then x+1 else x-1

(1)(jnz,&a,0,3)
(2)(jmp,0,0,7)
(3)(jnz,&b,0,5)
(4)(jmp,0,0,7)
(5)(+,&x,&1,&T1)
(6)(jmp,0,0,8)
(7)(-,&x,&1,&T2)
(8)other



if a&b&c then x+1 else x-1 other
(1)(jnz,&a,0,3)
(2)(jmp,0,0,9)
(3)(jnz,&b,0,5)
(4)(jmp,0,0,9)
(5)(jnz,&c,0,7)
(6)(jmp,0,0,9)
(7)(+,&x,1,&T1)
(8)(jmp,0,0,10)
(9)(-,&x,1,&T2)
(10)other


if aVb<c then S1 else S2

(1)(jnz,&a,0,3)
(2)(jmp,0,0,7)
(3)(j<,&b,&c,5)
(4)(jmp,0,0,7)
(5)S1
(6)(jmp,0,0,8)
(7)S2
(8)other



if b<cVa then S1 else S2

(1)(j<,&b,&c,5)
(2)(jmp,0,0,3)
(3)(jnz,&a,0,5)
(4)(jmp,0,0,7)
(5)S1
(6)(jmp,0,0,8)
(7)S2
(8)other

布尔表达式由若干子表达式构成,转移目标地址只有2个,或为真出口,或为假出口。为方便记录及回填,利用四元式的第四项构成2条单向链。赋予E、EA和EO以及.tc和.fc,分别记录需回填真假出口单向链的链首;

(1)(jnz,&x,0,0) <- E.tc = 1
(2)(jmp,0,0,0)	<- E.fc = i+1
... ...... ......
(p)(jnz,&x,0,i)	<- E.tc = p
(p+1)(jmp,0,0,i+1) <- E.fc = p+1

在分析过程中,利用语义值传递和合并链的方法,最终完成两根真假出口链的构造。在if-then-else语句中,当翻译完布尔表达式,就可以找到真出口,利用E.tc进行回填.当翻译完语句S1,就可知道假出口,利用E.fc进行回填。

e.g.
aVbVc

<i,“a”>
<V,nil>
<i,“b”>
<V,nil>
<i,“c”>

p100

stepstatussymbol.wval.addr四元式1.tc四元式2.fcnxq输入
00#----1<i,“a”>
08#i-a1<V,nil>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值