You are on page 1of 38

编译原理

自下而上分析

杨春明

西南科技大学计算机学院软件教研室
教学内容
„ 自下而上语法分析的基本问题
„ 算符优先分析(重点)
• 什么是算符优先分析法
• 优先表的构造
• 有限函数
„ LR分析法(重点)
„ 要求
• 正确理解自下而上语法分析的基本思想以及归约、短
语、句柄、分析树等概念,掌握算符优先分析基本方
法,算符优先表和和算符优先函数构造技术。 掌握LR
分析的基本方法及分析表的构造。
http://mryang.stumental.com/ 2
自下而上的语法分析
„ 自下而上的语法分析过程是最右推导的逆过
程(最左归约);即从输入串开始,朝着文
法开始符号进行归约,直至到达文法开始符
号为止的过程。
„ 自下而上分析同样可以定义一个PDA,这种
PDA是按一种“移进-归约”方式进行工作的,
也就是自左至右把输入串的符号一个个地移
进栈。在移进过程中,观察栈顶的符号串来
进行归约。
http://mryang.stumental.com/ 3
自下而上的语法分析
„ 自下而上分析PDA的框图如下:
• 输入带上记录了待识别的语句
• 读头自左至右扫描输
入串,初态时指在最左 输入带 a+b…#
单词符号上。
输出带
• 初态时栈底符为# 语法分析程序
语法表
• 语法分析的动作有: #
„移进、归约、识别成功、
识别失败 PDA框图
http://mryang.stumental.com/ 4
自下而上的语法分析
步骤 栈内 输入串 输出带 动作
0 # abbcde#
„ 例:文法如下:
1 #a bbcde# 移进
• (1)SÆaAcBe
2 #ab bcde# 移进
• (2)AÆb 3 #aA bcde# 2 归约
• (3)AÆAb 4 #aAb cde# 移进
• (4)BÆd 5 #aA cde# 2,3 归约
识别语句 6 #aAc de# 移进
abbcde 7 #aAcd e# 移进
8 #aAcB e# 2,3,4 归约
9 #aAcBe # 移进
10 #S # 2,3,4,1 归约
11 识别成功
http://mryang.stumental.com/ 5
自下而上的语法分析
„ 自下而上的语法分析过程中叶可能会有多个候选
式的情况,如何选择呢?
• 如果每次按句柄归约,就会成功。
• 因此,在这种分析过程中的关键问题就是找
句柄,按句柄进行规范归约才能正确分析语
句。
„ 确定的自下而上分析器通常分为两大类:
• 优先分析器(Precedence Parser)
• LR分析器

http://mryang.stumental.com/ 6
规范归约简述
„ 归约基本概念
• 短语,直接短语,句柄
„ 考虑文法
• E->T | E+T
• T->F | T*F
• F->I | (E)
• 考虑i+i*i 的短语、直接短语、句柄有哪些?

http://mryang.stumental.com/ 7
算符优先分析法
„ 算符优先分析法是一种特别有利于表达式分析,
宜于手工实现的语法分析方法。
„ 算符优先分析过程是自下而上的归约过程,但未
必是严格的最左归约,因此,它不是一种规范归
约法。
„ 算术表达式计算的基本口诀是:
• 先乘除后加减,同级从左算到右;
• 先括号内,后扩号外,一元负先于加减,后
于乘除,乘幂优先于乘。

http://mryang.stumental.com/ 8
算符优先分析
„ 所谓算符优先分析法就是仿效算术表达式的
运算过程而设计的一种语法分析方法;这种
方法的关键在于规定算符(终结符)的优先
顺序和结合性质。
„ 考虑下面的文法:
• EÆE+E | E-E |E*E | E/E | E↑E | (E) | i
• 这是一个二义文法,有几种不同的规范归约;
但是采用关于算符优先顺序和结合规则的规
定,并按这种规定归约,那么归约过程就是唯
一的。
http://mryang.stumental.com/ 9
算符优先分析
„ 算符优先分析法的关键是比较两个相继出
现的终结符的优先级而决定应采取的动作。
„ 要完成运算符间优先级的比较,最简单的
办法是先定义各种可能相继出现的运算符
的优先级,并将其表示成矩阵形式,在分
析过程中通过查询矩阵元素而获得算符间
的优先关系。

http://mryang.stumental.com/ 10
算符优先分析
„ 对于任何两个可能相继出现的终结符a和b具
有形式;“…ab…”或“…aQb…”,Q∈VN,
定义a,b之间有如下3种关系:
• (1)a≮ b a的优先级低于b
• (2)a≒ b a的优先级等于b
• (3)a≯ b a的优先级高于b
• 如果a和b在任何情况下不可能相继出现,则a,b
之间无关系;
• 要与‘<’或‘>’区分,a≮b不一定意味着b≯a
http://mryang.stumental.com/ 11
算符优先分析
„ 算术表达式文法终结符间的优先关系表
+ * ↑ i ( ) #
+ ≯ ≮ ≮ ≮ ≮ ≯ ≯
* ≯ ≯ ≮ ≮ ≮ ≯ ≯
↑ ≯ ≯ ≮ ≮ ≮ ≯ ≯
i ≯ ≯ ≯ ≯ ≯
( ≮ ≮ ≮ ≮ ≮ ≒
) ≯ ≯ ≯ ≯ ≯
# ≮ ≮ ≮ ≮ ≮ ≒
http://mryang.stumental.com/ 12
算符优先分析
„ 直观算符优先分析法:
• 使用两个工作栈OPTR(寄存运算符)和
OPND(存放“操作数”和“运算结果”);
• 开始,OPTR栈底放一个‘#’,输入串后也方一
个‘#’,OPND为空;
• 同时令θ 代表OPTR现行栈顶符号,a存放新
输入的符号;
• 则分析算法的基本步骤如下:

http://mryang.stumental.com/ 13
算符优先分析
„ 直观算符优先分析法
• (1)把下一个输入符号读至a中;
• (2)若a为i,则把它推进OPND,转向(1);
• (3)若θ≯a,则调用关于θ的处理程序,处理子表达
式E(1)θE(2),同时,把θ从OPTR栈顶逐出,然后重新
进入(3);
• (4)若θ≒a,则按优先表优两种可能:①
θ=‘(’,a=‘)’,此时逐出OPTR顶的‘(’,放弃a中的‘)’,然
后转(1);② θ=a=‘#’,结束;
• (5)若θ≮a,把a移进OPTR栈,转(1);
• (6) θ与a不存在优先关系,则输入串有错。

http://mryang.stumental.com/ 14
算符优先分析
„ 算符优先分析的缺点
• 会把错误的句子当作合法的句子来分析;如:i
i+i*+i()
• 不能指出输入串出错的准确位置;
• 对于含有一元运算“正(‘+’)”和“负(‘-’)”的算术表
达式不大好处理。
„ 算法优先分析法的优点:
• 简单明了,易于手工实现。

http://mryang.stumental.com/ 15
算符优先文法
„ 现在按照算符优先分析法的设计思路,构造
一种文法,通过它可以自动产生终结符的优
先关系表。
„ 定义1:给定上下文无关文法G,若G中没有
形如AÆ…BC…的产生式,则称G为算符文
法,其中A,B,C∈VN。
„ 注意:在以下的讨论中,我们假定算符文法
中不含有形如PÆε的产生式,也就是说不含
有ε-产生式。
http://mryang.stumental.com/ 16
算符优先文法
„ 定义2:设G是一个不包含有空串产生式的算符文
法,并设a,b∈VT;P,Q,R∈VN,对于任一对终结
符a,b有:
• 1、a≒b,当且仅当有PÆ…ab…或PÆ..aQb…
• 2、a≮b,当且仅当有PÆ…aR…或RÆ+b…或
RÆ+Qb…
• 3、 a≯b,当且仅当有PÆ…Rb…或RÆ+…a或
RÆ+…aQ
如果一个算符文法G中的任何终结符对(a,b)至
多满足上述三关系之一,则G就是一个算符优先
文法。 http://mryang.stumental.com/ 17
算符优先文法
„ 上述两个定义相当于对文法的句型和可归约短语
作了如下约定:
• 设A1A2…Ai-1AiAi+1…An是文法G的一个句型,则:
• (1)若Ai∈VN,则Ai-1,Ai+1∈ VT
• (2)若B1B2…Bm-1Bm是当前可归约短语,并可归约为
Ai,则:
• (a) B1B2…Bm-1Bm中不可能有相继两个非终结符且相
邻的终结符优先级全相等。
• (b) 对于B1B2…Bm的首终结符b有Ai-1≮ b;
• (c) 对于B1B2…Bm的尾终结符b有 b ≯ Ai-1 ;

http://mryang.stumental.com/ 18
算符优先表的构造
„ 通过检查G的每个产生式的每个候选式,可
找出所有满足a≒ b的终结符对。
„ 为了找出所有满足关系≮和≯的终结符对,
首先需要对G的每个非终结符P构造两个集
合:
• 定义:首终结符集合
FIRSTVT(P)={a|PÆ+a…或PÆ+Qa…}
• 定义:尾终结符集合LASTVT(P)={a|PÆ+…
a或PÆ+… aQ}
http://mryang.stumental.com/ 19
算符优先表的构造
„ 有了这两个集合之后,就可以通过检查每
个产生式的每个候选式,确定满足关系≮
和≯的所有终结符对。如,
„ 假定产生式右部右形如:…aP…的串,那
么对于任何b∈FIRSTVT(P),有a≮b
„ 假定产生式右部右形如:…Pb…的串,那
么对于任何a∈LASTVT(P),有a ≯ b

http://mryang.stumental.com/ 20
算符优先表的构造
„ 例:设文法G的产生式为:
SÆaAcBe AÆAb|b BÆ d
FIRSTVT(S)={a} a b c d e
FIRSTVT(A)={b} a ≮ ≒
FIRSTVT(B)={d}
b ≯ ≯
LASTVT(S)={e} c ≮ ≒
LASTVT(A)={b} d ≯
LASTVT(B)={d}
e
http://mryang.stumental.com/ 21
算符优先表的构造
„ 构造集合FIRSTVT(P)的算法
• 按FIRSTVT(P)的定义,可以用如下两条归则
来构造:
„ (1)若有产生式PÆa…或ÆQa…,则a∈
FIRSTVT(P)
„ (2)若a∈ FIRSTVT(Q),且有产生式PÆQ…,则

a∈ FIRSTVT(P)
• 构造算法:
„ 建立一个二维布尔数组F[P,a],使得F[P,a]为真的
条件适当且仅当a ∈ FIRSTVT(P);
http://mryang.stumental.com/ 22
算符优先表的构造
„ 构造算法
• 再用一个栈STACK,把所有初值为真的数组元素
F[P,a]的符号对(P,a)全都放到栈中;算法如下:
• (1)将布尔矩阵各元素置假;栈置空;
• (2)按照归则(1)查看产生式,对于PÆa…或
PÆQa..,置相应F[P,a]为真,符号对(P,a)入栈;
• (3)按规则(2),对栈施加如下操作:弹出栈定符号对
记作(Q,a),查看所有产生式是否有形如PÆQ…产生
式,若有,且a∈FIRSTVT(P),则将F[P,a]置为真,
并把(P,a)入栈;
• (4)重复(3),直到栈空为止。
http://mryang.stumental.com/ 23
算符优先表的构造
„ 构造集合LASTVT(P)的算法???
‰可根据LASTVT(P)的定义来构造,两条
规则:
ƒ(1)若有产生式PÆ…a或Æ…aQ,则a∈
LASTVT(P)
ƒ(2)若a∈ LASTVT(P) ,且有产生式
PÆ…Q,则a∈ LASTVT(P)

‰构造算法同FIRSTVT(P)的构造算法
http://mryang.stumental.com/ 24
算符优先表的构造
„ 构造优先表的算法:
FOR 每条产生式PÆX1X2…Xn DO PÆ…ab…
FOR I:=1 To n-1 DO PÆ…aQb
BEGIN …
IF Xi和Xi+1均为终结符 THEN 置Xi≒ Xi+1;
IF i≤n-2且Xi和Xi+2都为终结符但Xi+1为非终结符
THEN 置Xi≒ Xi+2;
IF Xi为终结符而Xi+1为非终结符 THEN PÆ…aR..
+
FOR FIRSTVT(Xi+1)中的每个a DO RÆ b…
RÆ +Qb…
置Xi≮ a;
IF Xi为非终结符而Xi+1为终结符 THEN
FOR FIRSTVT(Xi)中的每个a DO PÆ…Ra..
置a≯ Xi+1 ; RÆ+…a
END http://mryang.stumental.com/ RÆ+…aQ
25
算符优先分析的若干问题
„ 1)优先表构造算法的讨论
• 构造优先表的算法仅反映文法符号间关系,并
为反映附加条件,不能解决二义文法问题。
„ 2)非规范分析
• 算符优先分析是一种非规范分析,在这种分析
过程中,可归约的短语叫做最左素短语。
• 素短语至少含有一个终结符,且除它自身外,
不再包含其他素短语。
• 最左素短语指句型中最左边的那个素短语。
http://mryang.stumental.com/ 26
算符优先分析的若干问题
„ 3) 算符优先分析
• 假定我们把文法的句型的一般形式写成:
#N1a1N2a2…NnanNn+1#
• 其中ai是终结符,Ni是可有可无的非终结符。
• 设最左素短语是aj…NiaiNi+1则必定有:
aj-1≮aj aj≒aj+1≒ …≒ai ai≯ai+1
• 那么,ajNjaj+1…aiNi一定可归约为某终结符。
• 可将直观算符优先分析法改写成通用的算符优
先分析算法。

http://mryang.stumental.com/ 27
http://mryang.stumental.com/ 28
算符优先分析的若干问题
„ 4)算符优先分析的优缺点
• 优点:
• 算符优先分析比规范归约邀快得多;
• 算符优先分析文法使用的范围比简单文法大得
多;
• 缺点:
• 可能会把错误的句子识别正确;
• 某些文法不满足算符优先文法的要求。

http://mryang.stumental.com/ 29
优先函数
„ 把每一个终结符θ与一对整数f(θ),g(θ)
联系在一起,其中f(θ)为终结符θ在栈内
时的优先数,g(θ)为终结符θ(还未进栈
的优先数)的比较优先数。
„ f(θ)与g(θ)的值应满足如下关系:
• 若θ1≮θ2 则f(θ1)<g(θ2)
• 若θ1≒θ2 则f(θ1)=g(θ2)
• 若θ1≯θ2 则f(θ1)>g(θ2)

http://mryang.stumental.com/ 30
优先函数
„ 优先表与优先函数的关系
• 1)优先函数并不等价于优先表,在优先表中没
有关系的终结符对存在优先函数。
• 2)有些优先表不存在对应的优先函数f和g。
• 3)如果存在一对优先函数,则存在无穷多对优
先函数。不同的算法,从优先表转换为优先函
数时也可能得到不同的结果。

http://mryang.stumental.com/ 31
优先函数
„ 从优先表转换为优先函数的算法
„ 算法1:逐次加1法
• 1)对所有终结符a(包括#),令f(a):=g(a)=c
• 2)对所有终结符:
若a≯b而f(a) ≤g(b),则f(a):=g(b)+1
若a≮b而f(a) ≥g(b),则g(b):=f(a)+1
若a≒b而f(a) ≠g(b),则f(a)=g(b)=max(f(a),g(b))
• 3)重复步骤(2)直至f(a),g(b)不再改变为止。如果f(a)
或g(b)的任一值≥2n+c而步骤(2)还没结束,表示优
先函数不存在。
http://mryang.stumental.com/ 32
优先函数
例:由G(E)文法的优先表构造优先函数的过程

http://mryang.stumental.com/ 33
优先函数
„ 算法2:Bell有向图
• 1)对每个终结符a(包括#)令其对应两个节点fa
和ga,画一张以所有fa和ga为节点的有向图,
如果a≯b或a≒b,就从fa画一弧指向gb,若
a≮b或a≒b,则从gb画一弧指向fa;
• 2)令f(a)等于节点fa可达的节点数(包括自
身),令g(a)等于节点ga可达的节点数(包括自
身);
• 3)检查构造出来的f(a)和g(a),若与优先表符
合则优先函数存在,否则不存在。
http://mryang.stumental.com/ 34
优先函数
„ Bell有向图举例:

i * + #

f 6 6 4 2
g 7 5 3 2

http://mryang.stumental.com/ 35
练习
„ 有文法如下:
• E->E+T | T
• T->T*F |F
• F->(E)| i
„ 找出句型T+T*F*i+i 的所有短语、素短语

http://mryang.stumental.com/ 36
练习
„ 有文法如下:
• S->var IDT : TYPE
• IDT->IDT , i
• IDT->i
• TYPE->real | char
„ (1)构造文法的算符优先表
„ (2)分析句子var i , i : char

http://mryang.stumental.com/ 37
练习
„ 根据优先矩阵构造优先函数

S1 S2 S3 S4 S1 S2 S3 S4
S1 ≯ ≯ ≯ S1
S2 ≯ ≯ S2 ≒ ≒
S3 ≮ ≒ ≮ S3 ≯ ≯
S4 ≒ ≒ S4 ≮ ≮

http://mryang.stumental.com/ 38

You might also like