Download presentation
Presentation is loading. Please wait.
1
第三章 语法分析 本章内容 上下文无关文法 自上而下分析和自下而上分析 围绕分析器的自动生成展开 词 法 分析器 记 号 取下一个记号
第三章 语法分析 词 法 分析器 记 号 取下一个记号 源程序 分析树 前端的 其余部分 中间表示 符号表 本章内容 上下文无关文法 自上而下分析和自下而上分析 围绕分析器的自动生成展开
2
3.1 上下文无关文法 3.1.1 上下文无关文法的定义 正规式能定义一些简单的语言,能表示给定结构的固定次数的重复或者没有指定次数的重复
例:a (ba)5, a (ba)* 正规式不能用于描述配对或嵌套的结构 例1:配对括号串的集合 例2:{wcw | w是a和b的串}
3
3.1 上下文无关文法 上下文无关文法是四元组(VT , VN , S, P)
P : 产生式集合, 产生式形式 : A 例 ( {id, +, , , (, )}, {expr, op}, expr, P ) expr expr op expr expr (expr) expr expr expr id op op
4
3.1 上下文无关文法 简化表示 expr expr op expr | (expr) | expr | id op + |
E E A E | (E ) | E | id A + |
5
3.1 上下文无关文法 3.1.2 推导 例 E E + E | E E | (E ) | E | id 概念 记号
把产生式看成重写规则,把符号串中的非终结符用其产生式右部的串来代替 例 E E + E | E E | (E ) | E | id E E (E) (E + E) (id + E) (id + id) 概念 上下文无关语言、等价的文法、句型 记号 S *、 S + w
6
3.1 上下文无关文法 例 E E + E | E E | (E ) | E | id 最左推导 最右推导(规范推导)
E lm E lm (E) lm (E + E) lm (id + E) lm (id + id) 最右推导(规范推导) E rm E rm (E) rm (E + E) rm (E + id) rm (id + id)
7
3.1 上下文无关文法 3.1.3 分析树 例 E E + E | E E | (E ) | E | id E E ( E
8
3.1 上下文无关文法 3.1.4 二义性 E E E E E + E id E E E +E
id E + E id E + E id id + E id id + E id id + id id id + id 两个不同的最左推导
9
3.1 上下文无关文法 3.1.4 二义性 E E E E E + E id E E E +E
id E + E id E + E id id + E id id + E id id + id id id + id 两棵不同的语法树 E * + id
10
3.2 语言和文法 文法的优点 文法的问题 文法给出了精确的,易于理解的语法说明 自动产生高效的分析器 可以给语言定义出层次结构
以文法为基础的语言的实现便于语言的修改 文法的问题 文法只能描述编程语言的大部分语法,不能描述语言中上下文有关的语法特征
11
3.2 语言和文法 3.2.1 正规式和上下文无关文法的比较 正规式 文法 (a|b)*ab A0 a A0 | b A0 | a A1
开始 a b
12
3.2 语言和文法 3.2.2 分离词法分析器理由 为什么要用正规式定义词法 词法规则非常简单,不必用上下文无关文法
对于词法记号,正规式描述简洁且易于理解 从正规式构造出的词法分析器效率高
13
3.2 语言和文法 从软件工程角度看,词法分析和语法分析的分离有如下好处 简化设计 编译器的效率会改进 编译器的可移植性加强
便于编译器前端的模块划分
14
3.2 语言和文法 能否把词法分析并入到语法分析中,直接从字符流进行语法分析
若把词法分析和语法分析合在一起,则必须将语言的注解和空白的规则反映在文法中,文法将大大复杂 注解和空白由自己来处理的分析器,比注解和空格已由词法分析器删除的分析器要复杂得多
15
3.2 语言和文法 3.2.3 验证文法产生的语言 G : S (S) S | L(G) = 配对的括号串的集合
16
3.2 语言和文法 3.2.3 验证文法产生的语言 G : S (S) S | L(G) = 配对的括号串的集合
按推导步数进行归纳:推出的是配对括号串 归纳基础: S 归纳假设:少于n步的推导都产生配对的括号串 归纳步骤:n步的最左推导如下: S (S)S * (x) S * (x) y
17
3.2 语言和文法 3.2.3 验证文法产生的语言 G : S (S) S | L(G) = 配对的括号串的集合
归纳假设:长度小于2n的都可以从S推导出来 归纳步骤:考虑长度为2n(n 1)的w = (x) y S (S)S * (x) S * (x) y
18
3.2 语言和文法 适当的表达式文法 用一种层次观点看待表达式 id id (id+id) + id id + id
19
3.2 语言和文法 3.2.4 适当的表达式文法 用一种层次观点看待表达式 id id (id+id) + id id + id
适当的表达式文法 用一种层次观点看待表达式 id id (id+id) + id id + id id id (id+id) 文法 expr expr + term | term term term factor | factor factor id | (expr)
20
3.2 语言和文法 expr expr + term | term term term factor | factor
factor id | (expr) expr id term factor * expr + id factor term * id id id 分析树 id + id id 分析树
21
3.2 语言和文法 3.2.5 消除二义性 stmt if expr then stmt
| if expr then stmt else stmt | other 句型:if expr then if expr then stmt else stmt 两个最左推导: stmt if expr then stmt if expr then if expr then stmt else stmt stmt if expr then stmt else stmt
22
3.2 语言和文法 无二义的文法 stmt matched _stmt | unmatched_stmt
matched_stmt if expr then matched_stmt else matched_stmt | other unmatched_stmt if expr then stmt | if expr then matched_stmt else unmatched_stmt
23
3.2 语言和文法 3.2.6 消除左递归 文法左递归 A+Aa 直接左递归 AAa |b 消除直接左递归 A b A
串的特点 ba a 消除直接左递归 A b A A a A |
24
3.2 语言和文法 例 算术表达文法 E E + T | T ( T + T . . . + T )
T T F | F ( F F F ) F ( E ) | id 消除左递归后文法 E TE E + TE | T FT T F T |
25
3.2 语言和文法 非直接左递归 S Aa | b A Sd | 先变换成直接左递归 A Aad | bd |
再消除左递归 A bd A | A A adA |
26
3.2 语言和文法 3.2.7 提左因子 有左因子的文法 A 1 | 2 提左因子 A A A 1 | 2
27
3.2 语言和文法 例 悬空else的文法 stmt if expr then stmt else stmt
| other 提左因子 stmt if expr then stmt optional_else_part optional_else_part else stmt |
28
3.2 语言和文法 3.2.8 非上下文无关的语言构造 L1 = {wcw | w属于(a | b)*}
标识符的声明应先于其引用的抽象 L2 = {anbmcndm | n 0, m 0} 形参个数和实参个数应该相同的抽象 L3 = {anbncn | n 0} 早先排版描述的一个现象的抽象 b e g i n:5个字母键,5个回退键,5个下划线键
29
3.2 语言和文法 L1= {wcwR | w(a|b)*} S aSa | bSb | c
L2 = {anbmcmdn | n 1, m 1} S aSd | aAd A bAc | bc L 2 = {anbncmdm | n 1,m 1} S AB A aAb | ab B cBd | cd
30
3.2 语言和文法 L3 ={anbn | n 1} L3是不能用正规式描述的语言的一个范例 S aSb | ab
若存在接受L3 的DFA D,状态数为k个 设D读完, a, aa, …, ak 分别到达状态s0, s1, …, sk 至少有两个状态相同,例如是si和sj,则ajbi属于L3 si … f s0 标记为ai的路径 标记为bi的路径 标记为aj i的路径
31
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1
32
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 短语文法
33
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 短语文法
34
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 短语文法、上下文有关文法
35
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 2型文法:A ,AVN , (VN ∪VT)* 短语文法、上下文有关文法
36
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 2型文法:A ,AVN , (VN ∪VT)* 短语文法、上下文有关文法、上下文无关文法
37
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 2型文法:A ,AVN , (VN ∪VT)* 3型文法:A aB或A a,A, BVN , a VT 短语文法、上下文有关文法、上下文无关文法
38
3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P)
0型文法: , , (VN VT)*, | | 1 1型文法:| | | |,但S 可以例外 2型文法:A ,AVN , (VN ∪VT)* 3型文法:A aB或A a,A, BVN , a VT 短语文法、上下文有关文法、上下文无关文法、正规文法
39
3.2 语言和文法 例 L3={anbncn| n 1}的上下文有关文法 S aSBC S aBC CB BC
aB ab bB bb bC bc cC cc anbncn的推导过程如下: S * an-1S(BC)n1 用S aSBC n-1次 S + an(BC)n 用S aBC 1次 S + anBnCn 用CB BC交换相邻的CB S + anbBn1Cn 用aB ab 1次 S + anbnCn 用bB bb n-1次 S + anbncCn-1 用bC bc 次 S + anbncn 用cC cc n-1次
40
3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S aCb C cd | c 为输入串w = acb建立分析树
不能处理左递归
41
3.3 自上而下分析 不能处理左递归的例子 算术表达文法 E E + T | T T T F | F
F ( E ) | id E E + T E + T E + T … … …
42
3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S aCb C cd | c 为输入串w = acb建立分析树
不能处理左递归、复杂的回溯技术
43
3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S aCb C cd | c 为输入串w = acb建立分析树
不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来
44
3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S aCb C cd | c 为输入串w = acb建立分析树
不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来、难以报告出错的确切位置
45
3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S aCb C cd | c 为输入串w = acb建立分析树
不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来、难以报告出错的确切位置、效率低
46
3.3 自上而下分析 3.3.2 LL(1)文法 对文法加什么样的限制可以保证没有回溯? 先定义两个和文法有关的函数
FIRST( ) = {a | * a…, a VT} 特别是, * 时,规定 FIRST( ) 对A的任何两个不同选择i 和j,希望有 FIRST(i ) FIRST(j ) = 若FIRST(i ) 或 FIRST(j )含,还需增加条件
47
3.3 自上而下分析 3.3.2 LL(1)文法 对文法加什么样的限制可以保证没有回溯? 先定义两个和文法有关的函数
FIRST( ) = {a | * a…, a VT} 特别是, * 时,规定 FIRST( ) FOLLOW(A) = {a | S * …Aa…,aVT} 如果A是某个句型的最右符号,那么$属于FOLLOW(A)
48
3.3 自上而下分析 LL(1)文法 任何两个产生式A | 都满足下列条件: FIRST( ) FIRST( ) =
若 * ,那么FIRST() FOLLOW(A) = 例如, 对于下面文法,面临a…时,第2步推导不 知用哪个产生式 S A B A a b | a FIRST(ab) FOLLOW(A) B a C C …
49
3.3 自上而下分析 LL(1)文法 任何两个产生式A | 都满足下列条件: LL(1)文法有一些明显的性质
FIRST( ) FIRST( ) = 若 * ,那么FIRST() FOLLOW(A) = LL(1)文法有一些明显的性质 没有公共左因子 不是二义的 不含左递归
50
3.3 自上而下分析 例 E TE E + TE | T FT T FT |
F (E) | id FIRST(E) = FIRST(T) = FIRST(F) = { ( , id } FIRST(E ) = {+, } FRIST(T ) = {, } FOLLOW(E) = FOLLOW(E ) = { ), $} FOLLOW(T) = FOLLOW (T ) = {+, ), $} FOLLOW(F) = {+, , ), $} * 在FRIST(T)中,+, )和$在FOLLOW (T) 中。
51
3.3 自上而下分析 3.3.3 递归下降的预测分析 例 type simple | id
为每一个非终结符写一个分析过程 这些过程可能是递归的 例 type simple | id | array [simple] of type simple integer | char | num dotdot num
52
3.3 自上而下分析 一个辅助过程 void match (terminal t) {
if (lookahead == t) lookahead = nextToken( ); else error( ); }
53
3.3 自上而下分析 type simple | id | array [simple] of type
void type( ) { if ( (lookahead == integer) || (lookahead == char) || (lookahead == num) ) simple( ); else if ( lookahead == ) { match(); match(id);} else if (lookahead == array) { match(array); match( [ ); simple( ); match( ] ); match(of ); type( ); } else error( ); type simple | id | array [simple] of type
54
3.3 自上而下分析 void simple( ) { if ( lookahead == integer) match(integer);
else if (lookahead == char) match(char); else if (lookahead == num) { match(num); match(dotdot); match(num); } else error( ); simple integer | char | num dotdot num
55
3.3 自上而下分析 3.3.4 非递归的预测分析 a + b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈
56
3.3 自上而下分析 分析表的一部分 非终 结符 输 入 符 号 id + . . . E E TE E
输 入 符 号 id + . . . E E TE E E +TE T T FT T T T FT F F id
57
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
58
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE
59
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT
60
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT $E T id F id
61
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT $E T id F id $E T id + id$
62
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT $E T id F id $E T id + id$ $E T F T FT
63
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT $E T id F id $E T id + id$ $E T F T FT id + id$
64
3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id id + id$
输 入 输 出 $E id id + id$ $E T E TE $E T F T FT $E T id F id $E T id + id$ $E T F T FT id + id$
65
3.3 自上而下分析 3.3.5 构造预测分析表 (1)对文法的每个产生式A ,执行(2)和(3)
(2)对FIRST()的每个终结符a, 把A 加入M[A, a] (3)如果在FIRST()中,对FOLLOW(A)的每个终结符b(包括$), 把A 加入M[A, b] (4)M中其它没有定义的条目都是error
66
3.3 自上而下分析 多重定义的条目 非终 结符 输 入 符 号 other b else . . . stmt stmt other
输 入 符 号 other b else . . . stmt stmt other e_part e_part else stmt e_part expr expr b
67
3.3 自上而下分析 消去多重定义 非终 结符 输 入 符 号 other b else . . . stmt stmt other
输 入 符 号 other b else . . . stmt stmt other e_part e_part else stmt expr expr b
68
3.3 自上而下分析 3.3.6 预测分析的错误恢复 1、先对编译器的错误处理做一个概述 词法错误,如标识符、关键字或算符的拼写错
语法错误,如算术表达式的括号不配对 语义错误,如算符作用于不相容的运算对象 逻辑错误,如无穷的递归调用
69
3.3 自上而下分析 2、分析器对错误处理的基本目标 清楚而准确地报告错误的出现,并尽量少出现伪错误
迅速地从每个错误中恢复过来,以便诊断后面的错误 它不应该使正确程序的处理速度降低太多
70
3.3 自上而下分析 3、非递归预测分析在什么场合下发现错误 输入 预测分析程序 输出 栈 分析表M 栈顶的终结符和下一个输入符号不匹配 a
+ b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈
71
3.3 自上而下分析 3、非递归预测分析在什么场合下发现错误 输入 预测分析程序 输出 栈 分析表M
栈顶是非终结符A,输入符号是a,而M[A , a]是空白 a + b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈
72
3.3 自上而下分析 4、非递归预测分析:采用紧急方式的错误恢复 5、同步
发现错误时,分析器每次抛弃一个输入记号,直到输入记号属于某个指定的同步记号集合为止 5、同步 词法分析器当前提供的记号流能够构成的语法构造,正是语法分析器所期望的 不同步的例子 语法分析器期望剩余的前缀构成过程调用语句,而实际剩余的前缀形成赋值语句
73
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
74
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
if expr then stmt (then和分号等记号是expr的同步记号)
75
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
把高层构造的开始符号加到低层构造的同步记号集合中
76
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
把高层构造的开始符号加到低层构造的同步记号集合中 a = expr; if … (语句的开始符号作为表达式的同步记号,以免表达式出错又遗漏分号时忽略if语句等一大段程序)
77
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
把高层构造的开始符号加到低层构造的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 a = expr; , if … (语句的开始符号作为语句的同步符号,以免多出一个逗号时会把if语句忽略了)
78
3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
把高层构造的开始符号加到低层构造的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 如果非终结符可以产生空串,若出错时栈顶是这样的非终结符,则可以使用推出空串的产生式
79
3.3 自上而下分析 例 栈顶为T ,面临id时出错 非终 结符 输 入 符 号 id + . . . E ETE E
输 入 符 号 id + . . . E ETE E E+TE T TFT T 出错 T T FT
80
3.3 自上而下分析 T 可以产生空串,报错并用T 非终 结符 输 入 符 号 id + . . . E ETE E
输 入 符 号 id + . . . E ETE E E+TE T TFT T 出错, 用T T T FT
81
3.3 自上而下分析 同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合
把高层结构的开始符号加到低层结构的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 如果非终结符可以产生空串,若出错时栈顶是这样的非终结符,则可以使用推出空串的产生式 如果终结符在栈顶而不能匹配,弹出此终结符
82
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d
83
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde(读入ab) a b
84
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde(归约) a A
85
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde(再读入bc)
86
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde
aAde(归约) a b A c
87
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde
aAde(再读入d) a b A d c
88
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde aAde
89
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde aAde
aABe(再读入e) e a b A d c B
90
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde aAde
91
3.4 自下而上分析 3.4.1 归约 例 S aABe A Abc | b B d abbcde aAbcde aAde
S rm aABe rm aAde rm aAbcde rm abbcde S e a b A d c B
92
3.4 自下而上分析 3.4.2 句柄 句型的句柄是和某产生式右部匹配的子串,并且,把它归约成该产生式左部的非终结符代表了最右推导过程的逆过程的一步 S aABe A Abc | b B d S rm aABe rm aAde rm aAbcde rm abbcde 句柄的右边仅含终结符 如果文法二义,那么句柄可能不唯一
93
3.4 自下而上分析 例 句柄不唯一 E E + E | E E | (E ) | id
94
3.4 自下而上分析 例 句柄不唯一 E E + E | E E | (E ) | id E rm E E
例 句柄不唯一 E E + E | E E | (E ) | id E rm E E rm E E + E rm E E + id3 rm E id2 + id3 rm id1 id2 + id3
95
3.4 自下而上分析 例 句柄不唯一 E E + E | E E | (E ) | id
例 句柄不唯一 E E + E | E E | (E ) | id E rm E E E rm E + E rm E E + E rm E + id3 rm E E + id3 rm E E + id3 rm E id2 + id3 rm E id2 + id3 rm id1 id2 + id3 rm id1 id2 + id3 在句型E E + id3中,句柄不唯一
96
3.4 自下而上分析 3.4.3 用栈实现移进归约分析 先通过 来了解移进归约分析的工作方式
移进归约分析器在分析输入串id1 id2 + id3时的动作序列 来了解移进归约分析的工作方式
97
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$
98
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进
99
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
100
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约
101
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E
102
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E
103
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$
104
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$
105
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$
106
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$
107
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE
108
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE
109
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$
110
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$
111
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3
112
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3
113
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E
114
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E E+E归约
115
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E E+E归约
116
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E E+E归约 按E EE归约
117
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E E+E归约 按E EE归约
118
3.4 自下而上分析 栈 输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$
输 入 动 作 $ id1 id2 + id3$ 移进 $ id1 id2 + id3$ 按E id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E E+E归约 按E EE归约 接受
119
3.4 自下而上分析 要想很好地使用移进归约方式,尚需解决一些问题 如何决策选择移进还是归约 进行归约时,确定右句型中将要归约的子串
进行归约时,如何确定选择哪一个产生式
120
3.4 自下而上分析 3.4.4 移进归约分析的冲突 1、移进归约冲突 例 stmt if expr then stmt
| if expr then stmt else stmt | other 如果移进归约分析器处于格局 栈 输入 … if expr then stmt else … $
121
3.4 自下而上分析 2、归约归约冲突 stmt id (parameter_list) | expr = expr
parameter_list parameter_list, parameter | parameter parameter id expr id (expr_list) | id expr_list expr_list, expr | expr 由A(I, J)开始的语句 栈 输入 … id ( id , id )… 归约成expr还 是parameter ?
122
3.4 自下而上分析 2、归约归约冲突 stmt id (parameter_list) | expr = expr
parameter_list parameter_list, parameter | parameter parameter id expr id (expr_list) | id expr_list expr_list, expr | expr 由A(I, J)开始的语句(词法分析查符号表,区分第一个id) 栈 输入 … procid ( id , id )… 需要修改上面的文法
123
3.5 LR分析器 本节介绍LR(k)分析技术 特点 主要介绍构造LR分析表的三种技术 适用于一大类上下文无关文法 效率高
简单的LR方法(简称SLR) 规范的LR方法 向前看的LR方法(简称LALR)
124
3.5 LR分析器 3.5.1 LR分析算法 输入 LR分析程序 输出 栈 LR分析器的模型 action goto sm Xm Xm-1
… s0 a1 ai an $
125
3.5 LR分析器 例 E E + T | E T T T F | T E F (E ) | F id 状态
动 作 转 移 id ( ) $ E T F s s4 1 s acc 2 r2 s r2 r2 3 r4 r r4 r4 4
126
3.5 LR分析器 栈 输 入 动 作 id id + id $
127
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进
128
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $
129
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
130
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3
131
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约
132
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2
133
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2
134
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $
135
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $
136
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $
137
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $
138
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10
139
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约
140
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约 . . .
141
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约 . . . 0 E 1 $
142
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约 . . . 0 E 1 $ 接受
143
3.5 LR分析器 3.5.2 LR文法和LR分析方法的特点 1、概念 活前缀:右句型的前缀,该前缀不超过最右句柄的右端
S *rm A w rm w 的任何前缀(包括和 本身)都是活前缀
144
3.5 LR分析器 3.5.2 LR文法和LR分析方法的特点 1、概念 活前缀:右句型的前缀,该前缀不超过最右句柄的右端 2、定义
145
3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀
146
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约 . . . 0 E 1 $ 接受
147
3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA
148
3.5 LR分析器 例 E E + T | E T 下表绿色部分构成 T T F | T E 识别活前缀DFA的
F (E ) | F id 状态转换表 状态 动 作 转 移 id ( ) $ E T F s s4 1 s acc 2 r2 s r2 r2 3 r4 r r4 r4 4
149
3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA
栈顶的状态符号包含了确定句柄所需要的一切信息
150
3.5 LR分析器 栈 输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约
输 入 动 作 id id + id $ 移进 0 id 5 id + id $ 按F id归约 0 F 3 按T F归约 0 T 2 0 T 2 7 id + id $ 0 T 2 7 id 5 + id $ 0 T 2 7 F 10 按T TF归约 . . . 0 E 1 $ 接受
151
3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA
栈顶的状态符号包含了确定句柄所需要的一切信息 是已知的最一般的无回溯的移进归约方法 能分析的文法类是预测分析法能分析的文法类的真超集 能及时发现语法错误 手工构造分析表的工作量太大
152
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上
自 上 而 下
153
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上
自 上 而 下 归约还是推导 规 范 归 约 最 左 推 导
154
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 在下面的推导中,最后一步用的是A l
S rm … rm A b w rm l b w LR(1)决定用该 产生式的位置 LL(1)决定用该 产生式的位置
155
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上
自 上 而 下 归约还是推导 规 范 归 约 最 左 推 导 决定使用产生式的时机 看见产生式右部推出的整个终结符串后,才确定用哪个产生式进行归约 看见产生式右部推出的第一个终结符后,便要确定用哪个产生式推导
156
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制
无左递归、无公共左因子
157
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制
无左递归、无公共左因子 分析表比较 状态×文法符号 分析表大 非终结符×终结符 分析表小
158
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制
无左递归、无公共左因子 分析表比较 状态×文法符号 分析表大 非终结符×终结符 分析表小 分析栈比较 状态栈,通常状态比文法符号包含更多信息 文法符号栈
159
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 确定句柄
根据栈顶状态和下一个符号便可以确定句柄和归约所用产生式 无句柄概念
160
3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 确定句柄
根据栈顶状态和下一个符号便可以确定句柄和归约所用产生式 无句柄概念 语法错误 决不会将出错点后的符号移入分析栈 和LR一样,决不会读过出错点而不报错
161
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式
162
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式
加点的目的是用来表示分析过程中的状态
163
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式
加点的目的是用来表示分析过程中的状态 expr + term
164
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式
加点的目的是用来表示分析过程中的状态 expr + term * factor
165
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式
加点的目的是用来表示分析过程中的状态 expr + term * factor
166
3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 例 AXYZ对应有四个项目
在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态 例 AXYZ对应有四个项目 A ·XYZ A X·YZ A XY·Z A XYZ· 例 A 只有一个项目和它对应 A ·
167
3.5 LR分析器 构造SLR分析表的两大步骤 1、从文法构造识别活前缀的DFA 2、从上述DFA构造分析表
168
3.5 LR分析器 1、从文法构造识别活前缀的DFA 1)拓广文法 E E + T | T T T F | F
F ( E ) | id
169
3.5 LR分析器 1、从文法构造识别活前缀的DFA 1)拓广文法 E E E E + T | T T T F | F
F ( E ) | id
170
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E
171
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E ·E + T
172
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E ·E + T
T ·T F T ·F
173
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E ·E + T
T ·T F T ·F F ·(E) F ·id
174
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E (核心项目)
E ·E + T E ·T (非核心项目, T ·T F 通过对核心项目求闭包 T ·F 而获得) F ·(E) F ·id
175
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: I1: E ·E E E·
E ·E + T E E· + T E ·T T ·T F T ·F F ·(E) F ·id E
176
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: I1: E ·E E E·
E ·E + T E E· + T E ·T T ·T F I1 := goto ( I0, E ) T ·F F ·(E) F ·id E
177
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: I1: E ·E E E·
E ·E + T E E· + T E ·T T ·T F I2: T ·F E T· F ·(E) T T· F F ·id E T
178
3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: I1: E ·E E E·
E ·E + T E E· + T E ·T T ·T F I2: T ·F E T· F ·(E) T T· F F ·id I3: T F· E T F
179
3.5 LR分析器 I0: I4: E ·E F (·E ) ( E ·E + T E ·T T ·T F
F ·id (
180
3.5 LR分析器 I0: I4: E ·E F (·E ) ( E ·E + T E ·E + T
E ·T E ·T T ·T F T ·T F T ·F T ·F F ·(E) F ·(E) F ·id F ·id (
181
3.5 LR分析器 I0: I4: E ·E F (·E ) ( E ·E + T E ·E + T
E ·T E ·T T ·T F T ·T F T ·F T ·F F ·(E) F ·(E) F ·id F ·id I5: F id· ( id
182
3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id
183
3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I1: E E· E E·+ T
184
3.5 LR分析器 I1: E E· E E·+ T I6 : EE + ·T T ·T F T ·F +
( id I1: E E· E E·+ T I6 : EE + ·T T ·T F T ·F F ·(E) F ·id +
185
3.5 LR分析器 I1: I2: E E· ET· E E·+ T TT·F I6 : EE + ·T
( id I1: I2: E E· ET· E E·+ T TT·F I6 : EE + ·T T ·T F T ·F F ·(E) F ·id +
186
3.5 LR分析器 I1: I2: E E· ET· E E·+ T TT·F I6 : I7:
( id I1: I2: E E· ET· E E·+ T TT·F I6 : I7: EE + ·T TT·F T ·T F F ·(E) T ·F F ·id F ·(E) F ·id +
187
3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I3: T F· 无状态转换
188
3.5 LR分析器 I4: F (·E ) E ·E + T E ·T T ·T F T ·F F ·( E )
id I4: F (·E ) E ·E + T E ·T T ·T F T ·F F ·( E ) F ·id
189
3.5 LR分析器 I4: I8: F (·E ) F (E·) E E ·E + T E E·+ T E ·T
id I4: I8: F (·E ) F (E·) E ·E + T E E·+ T E ·T T ·T F T ·F F ·( E ) F ·id E
190
3.5 LR分析器 I4: I8: F (·E ) F (E·) E E ·E + T E E·+ T E ·T
id I4: I8: F (·E ) F (E·) E ·E + T E E·+ T E ·T T ·T F I2: T ·F ET· F ·( E ) TT·F F ·id E T
191
3.5 LR分析器 I4: I8: F (·E ) F (E·) E E ·E + T E E·+ T E ·T
id I4: I8: F (·E ) F (E·) E ·E + T E E·+ T E ·T T ·T F I2: T ·F ET· F ·( E ) TT·F F ·id I3: TF· E T F
192
3.5 LR分析器 I4: I8: F (·E ) F (E·) E E ·E + T E E·+ T E ·T
id I4: I8: F (·E ) F (E·) E ·E + T E E·+ T E ·T T ·T F I2: T ·F ET· F ·( E ) TT·F F ·id I3: TF· I4: F (·E ) . . . E T F (
193
3.5 LR分析器 I4: I8: F (·E ) F (E·) E E ·E + T E E·+ T E ·T
id I4: I8: F (·E ) F (E·) E ·E + T E E·+ T E ·T T ·T F I2: T ·F ET· F ·( E ) TT·F F ·id I3: TF· I4: I5: F (·E ) F id· . . . E T F ( id
194
3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I5: F id· 无状态转换
195
3.5 LR分析器 I1 I0 + E I6 I3 I2 I4 I8 I7 I5 指向I2 指向I3 T * F ( id
196
3.5 LR分析器 把所有状态都作为接受状态 这是一个DFA E E E+T E+T F E+T id
* T I5 指向I4 指向I3 指向I5 指向I6 指向I2 F ( id ) 把所有状态都作为接受状态 这是一个DFA E E E+T E+T F E+T id E+T F id E+T F 的所有前缀都可接受
197
3.5 LR分析器 也可以构造一个识别活前缀的NFA N I0: E ·E E ·E + T E ·T T ·T F
F ·(E) F ·id
198
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
T ·T F T ·F F ·(E) F ·id
199
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
E ·T E ·E + T E ·T T ·T F T ·F F ·(E) F ·id
200
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
E ·T E ·E + T E ·T T ·T F T ·F F ·(E) F ·id
201
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
E ·T E ·E + T E ·T T ·T F T ·F T ·T F T ·F F ·(E) F ·id
202
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
E ·T E ·E + T E ·T T ·T F T ·F T ·T F T ·F F ·(E) F ·id
203
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E ·E + T
E ·T E ·E + T E ·T T ·T F T ·F T ·T F T ·F F ·(E) F ·id F ·(E) F ·id
204
3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E ·E E ·E E E·
E ·E + T E ·T E ·E + T E ·T T ·T F T ·F T ·T F T ·F F ·(E) F ·id F ·(E) F ·id E
205
3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目
如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 E ·E+T对 和 ( 这两个活前缀都有效 E E E+T (,1都为空) E E (E) (E+T) ( =“(”,1为空) 该DFA读过 和(后到达不同的状态,那么项目 E · E+T就出现在对应的不同项目集中
206
3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目
如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 从项目A1·2对活前缀1有效这个事实可以知道 如果2 ,应该移进 如果2=, 应该用产生式A1归约
207
3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目
如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 (2)一个活前缀可能有多个有效项目 一个活前缀的有效项目集就是从这个DFA的初态出发,沿着标记为的路径到达的那个项目集(状态)
208
3.5 LR分析器 例 串E + T 是活前缀,读完它后,DFA处于状态I7 I7: TT ·F, F ·(E ), F ·id
E E E E E E E+T E+T E+T E+T F E+T F E+T F E+T id E+T (E ) E+T id E+T F id
209
3.5 LR分析器 构造SLR分析表的两大步骤 1、从文法构造识别活前缀的DFA 2、从上述DFA构造分析表
210
3.5 LR分析器 2、从DFA构造SLR分析表 状态i从Ii构造,它的action函数如下确定:
如果[A·a]在Ii中,并且goto(Ii, a ) = Ij,那么置action[i, a]为sj 如果[A·]在Ii中,那么对FOLLOW(A)中的所有a,置action[i, a]为rj,j是产生式 A的编号 如果[SS·]在Ii中,那么置action[ i, $ ]为接受acc 如果出现动作冲突,那么该文法就不是SLR(1) 的
211
3.5 LR分析器 2、从DFA构造SLR分析表 状态i从Ii构造,它的action函数如下确定: 使用下面规则构造状态i的goto函数:
. . . 使用下面规则构造状态i的goto函数: 对所有的非终结符A,如果goto(Ii, A) = Ij, 那么goto[i, A] = j
212
3.5 LR分析器 2、从DFA构造SLR分析表 状态i从Ii构造,它的action函数如下确定: 使用下面规则构造状态i的goto函数:
. . . 使用下面规则构造状态i的goto函数: 不能由上面两步定义的条目都置为error 分析器的初始状态是包含[S·S]的项目集对应的状态
213
3.5 LR分析器 例 I2: E T· T T· F 因为FOLLOW(E) = {$, +, )}, 所以 action[2, $]=action[2, +]=action[2, )]=r2 action[2, ] = s7
214
3.5 LR分析器 例 SLR(1)文法的描述能力有限 S V = E S E V E V id E V I0 :
S · S S ·V = E S · E V · E V · id E · V I2 : S V · = E E V · V 第一项目使得action[2, = ] = s6 第二项目使得 action[2, = ]为按 EV归约,因为=是 E的一个后继符 =是E的一个后继符: S $ V = E $ E = E $
215
3.5 LR分析器 例 SLR(1)文法的描述能力有限 S V = E S E V E V id E V I0 :
S · S S ·V = E S · E V · E V · id E · V I2 : S V · = E E V · V 第一项目使得action[2, = ] = s6 第二项目使得 action[2, = ]为按 EV归约,因为=是 E的一个后继符 在所关注场合E的后继是$: S $ V = E $ E = E $ S $ E $ V $
216
3.5 LR分析器 3.5.4 构造规范的LR分析表 LR(1)项目: 重新定义项目,让它带上搜索符,成为如下形式
[A ·, a] LR(1)项目[A ·, a]对活前缀有效: 如果存在着推导S *rm Aw rm w,其中: = ; a是w的第一个符号,或者w是且a是$
217
3.5 LR分析器 例 S BB B bB | a 从最右推导S *rm bbBba rm bbbBba看出:
[Bb·B, b]对活前缀 = bbb是有效的 对于项目[A ·, a],当为空时,是根据搜索符a来填表(归约项目),而不是根据A的后继符来填表
218
3.5 LR分析器 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
219
3.5 LR分析器 S S ·S, $ I0 S S·, $ I1 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b
220
3.5 LR分析器 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a S S·, $ I1
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8
221
3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA
(2)从Ii构造分析器的状态i, 状态i的action函数如下确定 如果[A ·a, b]在Ii中,且goto(Ii, a) = Ij ,那么置action[i, a]为sj 如果[A · , a]在Ii中,且A S,那么置action[i, a]为rj 如果[SS·, $]在Ii中,那么置action[i, $] = acc 如果用上面规则构造出现了冲突,那么文法就不是LR(1)的
222
3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA
(2)从Ii构造分析器的状态i, 状态i的action函数如下确定 . . . (3) 状态i的goto函数如下确定: 如果goto(Ii, A) = Ij, 那么goto[i, A] = j
223
3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA
(2)从Ii构造分析器的状态i, 状态i的action函数如下确定 . . . (3) 状态i的goto函数如下确定: (4) 用上面规则未能定义的所有条目都置为error
224
3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA
(2)从Ii构造分析器的状态i, 状态i的action函数如下确定 . . . (3) 状态i的goto函数如下确定: (4) 用上面规则未能定义的所有条目都置为error (5) 分析器的初始状态是包含[S·S, $]的项目集对应的状态
225
3.5 LR分析器 先前基于SLR(1)有移进-归约冲突的例子,在基于规范LR(1)时无冲突 S V = E S E V E
V id E V I0 : S · S, $ S ·V = E, $ S · E, $ V · E, =/$ V · id, =/$ E · V, $ I2 : S V · = E, $ E V ·, $ V
226
3.5 LR分析器 3.5.5 构造LALR分析表 研究LALR的原因 LALR特点 LALR分析表构造方法 规范LR分析表的状态数偏多
LALR和SLR的分析表有同样多的状态,比规范LR分析表要小得多 LALR的能力介于SLR和规范LR之间 LALR的能力在很多情况下已经够用 LALR分析表构造方法 通过合并规范LR(1)项目集来得到
227
3.5 LR分析器 I4和I7仅搜索符不一样 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8 I4和I7仅搜索符不一样
228
3.5 LR分析器 I4和I7合并 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8 I4和I7合并
229
3.5 LR分析器 输入为bbabba$ S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8 输入为bbabba$
230
3.5 LR分析器 输入为bba$ S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8 输入为bba$
231
3.5 LR分析器 有三组同心集,都合并 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a B ·a, b/a I3 B a·, b/a I4 a b S BB·, $ I5 B b·B, $ B ·a, $ I6 B bB·, $ I9 B a·, $ I7 B bB·, b/a I8 有三组同心集,都合并
232
3.5 LR分析器 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a S S·, $ I1
B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89
233
3.5 LR分析器 栈 输入 0 bba$ S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 bba$
234
3.5 LR分析器 栈 输入 0b36 ba$ S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0b ba$
235
3.5 LR分析器 栈 输入 0b36b36 a$ S ·S, $ I0 S ·BB, $ B ·bB, b/a
B ·a, b/a S S·, $ I1 S B·B, $ B ·bB, $ B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0b36b a$
236
3.5 LR分析器 栈 输入 0b36b36a47 $ S ·S, $ I0 S ·BB, $ B ·bB, b/a
B ·a, b/a S S·, $ I1 S B·B, $ B ·bB, $ B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0b36b36a $
237
3.5 LR分析器 栈 输入 0b36b36B89 $ S ·S, $ I0 S ·BB, $ B ·bB, b/a
B ·a, b/a S S·, $ I1 S B·B, $ B ·bB, $ B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0b36b36B $
238
3.5 LR分析器 栈 输入 0b36B89 $ S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0b36B $
239
3.5 LR分析器 栈 输入 0B2 $ 报错 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a
B ·a, $ I2 S B B b·B, b/a/$ B ·bB, b/a/$ B ·a, b/a/$ I36 B a·, b/a/$ I47 a b S BB·, $ I5 B bB·, b/a/$ I89 栈 输入 0B $ 报错
240
3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心的LR(1)项目集: 略去搜索符后它们是相同的集合
241
3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心集的合并不会引起新的移进归约冲突 项目集1 项目集2
项目集1 项目集2 [A ·, a] [B·a, b] 若合并后有冲突
242
3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心集的合并不会引起新的移进归约冲突 项目集1 项目集2
项目集1 项目集2 [A ·, a] [B·a, b] [B·a, c] [A ·, d] 则合并前就有冲突
243
3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心集的合并不会引起新的移进归约冲突 同心集的合并有可能产生新的归约归约冲突
S S S aAd | bBd | aBe | bAe A c B c 对ac有效的项目集 对bc有效的项目集 A c ·, d B c ·, e A c ·, e B c ·, d 合并同心集后 该文法是LR(1)的, 但不是LALR(1)的 A c ·, d/e B c ·, d/e
244
3.5 LR分析器 2、构造LALR(1)分析表 (1) 构造LR(1)项目集规范族C = {I0, I1, …, In}
245
3.5 LR分析器 下面文法是LALR(1)的,因无同心集可合并 但不是SLR(1)的 S V = E S E V E
V id E V I0 : S · S, $ S ·V = E, $ S · E, $ V · E, =/$ V · id, =/$ E · V, $ I2 : S V · = E, $ E V ·, $ V
246
3.5 LR分析器 3.5.6 非LR的上下文无关结构 若自左向右扫描的移进归约分析器能及时识别出现在栈顶的句柄,那么相应的文法就是LR的
语言L = {wwR| w (a | b)*}的文法 S aSa | bSb | 不是LR的 ababbbbaba 语言L = {wcwR| w (a | b)*}的文法 S aSa | bSb | c 是LR的 ababbcbbaba
247
3.5 LR分析器 例 为语言L = { ambn | n > m 0 }写三个文法,它们分别是LR(1)的、二义的和非二义且非LR(1)的 LR(1)文法:S AB A aAb | B Bb | b a a a b b b b b
248
3.5 LR分析器 例 为语言L = { ambn | n > m 0 }写三个文法,它们分别是LR(1)的、二义的和非二义且非LR(1)的 LR(1)文法:S AB A aAb | B Bb | b 非二义且非LR(1)的文法:S aSb | B B Bb | b a a a b b b b b
249
3.5 LR分析器 例 为语言L = { ambn | n > m 0 }写三个文法,它们分别是LR(1)的、二义的和非二义且非LR(1)的 LR(1)文法:S AB A aAb | B Bb | b 非二义且非LR(1)的文法:S aSb | B B Bb | b 二义的文法:S aSb | Sb | b a a a b b b b b
250
3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然
3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 例 二义文法 E E + E | E E | (E) | id 非二义的文法: E E + T | T T T F | F F (E) | id 该文法有单个非终结符为右部的产生式
251
3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 可以用文法以外的信息来消除二义
3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 可以用文法以外的信息来消除二义 语法分析的效率高(基于消除二义后得到的分析表)
252
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合
253
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I7 E E + E· E E·+ E E E· E
254
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I7 E E + E· E E·+ E id + id + id E E· E 面临+,归约
255
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I7 E E + E· E E·+ E id + id + id E E· E id + id id 面临+,归约 面临,移进
256
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I7 E E + E· E E·+ E id + id + id E E· E id + id id 面临+,归约 面临,移进 面临 ) 和$,归约
257
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I8 E E E· E E·+ E E E· E
258
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I8 E E E· E E·+ E id id + id E E· E 面临+,归约
259
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I8 E E E· E E·+ E id id + id E E· E id id id 面临+,归约 面临,归约
260
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突
3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E E + E | E E | (E) | id 规定: 优先级高于+,两者都是左结合 LR(0)项目集I8 E E E· E E·+ E id id + id E E· E id id id 面临+,归约 面临,归约 面临 ) 和$,归约
261
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E E E sup E E {E} E c
262
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E E E sup E E {E} E c 从定义形式语言的角度说,第一个产生式是多余的
263
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E E E sup E E {E} E c 联系到语义处理,第一个产生式是必要的
264
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E E E sub E E E sup E E {E} E c 对a sub i sup 2,需要下面第一种输出
265
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E I11:
3.6 二义文法的应用 3.6.2 特殊情况产生式引起的二义性 E E sub E sup E I11: E E sub E E E sub E sup E· E E sup E E E sup E· E {E} E c 按前面一个产生式归约
266
3.6 二义文法的应用 3.6.3 LR分析的错误恢复 1、LR分析器在什么情况下发现错误 访问动作表时若遇到出错条目
3.6 二义文法的应用 3.6.3 LR分析的错误恢复 1、LR分析器在什么情况下发现错误 访问动作表时若遇到出错条目 访问转移表时它决不会遇到出错条目 决不会把不正确的后继移进栈 规范的LR分析器甚至在报告错误之前决不做任何无效归约
267
3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 . . . . . . . . a . . A 发现错误 s : C ·A
3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 a . . A 发现错误 s : C ·A A· b . . . s1 : C A· Ab· b
268
3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 . . . . . . . . a . . A 发现错误 s : C ·A
3.6 二义文法的应用 2、紧急方式错误恢复 (1) 退栈,直至出现状态s, 它有预先确定的A的转移 s . 栈 a . . A 发现错误 s : C ·A A· b . . . s1 : C A· Ab· b
269
3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 . . . . . . . . a . . A s : C ·A
3.6 二义文法的应用 2、紧急方式错误恢复 (1) 退栈,直至出现状态s, 它有预先确定的A的转移 (2)抛弃若干输入符号,直至找到a, 它是A的合法后继 s . 栈 a . . A s : C ·A A· b . . . s1 : C A· Ab· b
270
3.6 二义文法的应用 2、紧急方式错误恢复 s s1 . 栈 . . . . . . . . a . . A s : C ·A
3.6 二义文法的应用 2、紧急方式错误恢复 (1) 退栈,直至出现状态s, 它有预先确定的A的转移 (2)抛弃若干输入符号,直至找到a, 它是A的合法后继 (3) 再把A和状态goto[s, A]压进栈,恢复正常分析 s s1 . 栈 a . . A s : C ·A A· b . . . s1 : C A· Ab· b
271
3.7 分析器的生成器 3.7.1 分析器的生成器Yacc Yacc 编译器 Yacc源程序 translate.y y.tab.c C
3.7 分析器的生成器 3.7.1 分析器的生成器Yacc Yacc 编译器 Yacc源程序 translate.y y.tab.c C a.out 输入 输出
272
3.7 分析器的生成器 3.7.2 用Yacc处理二义文法 例 简单计算器 输入一个表达式并回车,显示计算结果 也可以输入一个空白行
273
3.7 分析器的生成器 %{ # include <ctype .h> # include <stdio.h >
3.7 分析器的生成器 %{ # include <ctype .h> # include <stdio.h > # define YYSTYPE double /将栈定义为double类型 / %} %token NUMBER %left ‘+’ ‘’ %left ‘’ ‘/ ’ %right UMINUS %%
274
3.7 分析器的生成器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) }
3.7 分析器的生成器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) } | lines ‘\n’ | / / ; expr : expr ‘+’ expr {$$ = $1 + $3; } | expr ‘’ expr {$$ = $1 $3; } | expr ‘’ expr {$$ = $1 $3; } | expr ‘/ ’ expr {$$ = $1 / $3; } | ‘(’ expr ‘)’ {$$ = $2; } | ‘’ expr %prec UMINUS {$$ = $2; } | NUMBER %%
275
3.7 分析器的生成器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) }
3.7 分析器的生成器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) } | lines ‘\n’ | / / ; expr : expr ‘+’ expr {$$ = $1 + $3; } | expr ‘’ expr {$$ = $1 $3; } | expr ‘’ expr {$$ = $1 $3; } | expr ‘/ ’ expr {$$ = $1 / $3; } | ‘(’ expr ‘)’ {$$ = $2; } | ‘’ expr %prec UMINUS {$$ = $2; } | NUMBER %% -5+10看成是-(5+10), 还是(-5)+10? 取后者
276
3.7 分析器的生成器 yylex ( ) { int c; while ( ( c = getchar ( ) ) == ‘ ’ );
3.7 分析器的生成器 yylex ( ) { int c; while ( ( c = getchar ( ) ) == ‘ ’ ); if ( ( c == ‘.’ ) | | (isdigit (c) ) ) { ungetc (c, stdin); scanf ( “% lf ”, &yylval); return NUMBER; } return c; 为了C编译器能准确报告yylex函数中错误的位置, 需要在生成的程序y.tab.c中使用编译命令#line
277
3.7 分析器的生成器 3.7.3 Yacc的错误恢复 编译器设计者的工作 Yacc把错误产生式当作普通产生式处理
3.7 分析器的生成器 3.7.3 Yacc的错误恢复 编译器设计者的工作 决定哪些“主要的”非终结符将有错误恢复与它们相关联 为各主要非终结符A加入形式为A error 的错误产生式,其中是文法符号串 为这样的产生式配上语义动作 Yacc把错误产生式当作普通产生式处理
278
3.7 分析器的生成器 遇到语法错误时 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2
3.7 分析器的生成器 遇到语法错误时 s . 栈 A 发现错误 s : C 1·A2 A ·error . . . s1 : C1A·2 s2 : A error· error
279
3.7 分析器的生成器 遇到语法错误时 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2
3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 s . 栈 A 发现错误 s : C 1·A2 A ·error . . . s1 : C1A·2 s2 : A error· error
280
3.7 分析器的生成器 遇到语法错误时 s s2 . 栈 . . . . . . . . . . . A 发现错误 s :
3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 s s2 . 栈 A 发现错误 s : C 1·A2 A ·error . . . s1 : C1A·2 s2 : A error· error
281
3.7 分析器的生成器 遇到语法错误时 栈 . . . . . . . . . . . A s : C 1·A2
3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 忽略若干输入符号,直至找到,把移进栈 栈 A s : C 1·A2 A ·error . . . s1 : C1A·2 s2 : A error· error s s2 .
282
3.7 分析器的生成器 遇到语法错误时 s s1 . 栈 . . . . . . . . . . . A s : C 1·A2
3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 忽略若干输入符号,直至找到,把移进栈 把error 归约为A,恢复正常分析 s s1 . 栈 A s : C 1·A2 A ·error . . . s1 : C1A·2 s2 : A error· error
283
3.7 分析器的生成器 增加错误恢复的简单计算器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) } | lines ‘\n’ | / / | error ‘\n’{yyerror ( “重新输入上一行”); yyerrok;} ;
284
本 章 要 点 文法和语言的基本知识 自上而下的分析方法:预测分析,非递归的预测分析,LL(1)文法
本 章 要 点 文法和语言的基本知识 自上而下的分析方法:预测分析,非递归的预测分析,LL(1)文法 自下而上的分析方法:SLR(1)方法,规范LR(1)方法和LALR(1)方法 LR方法如何用于二义文法 语法分析的错误恢复方法
285
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法 S S and S | S or S | not S | p | q | (S) 非二义文法的产生式如下: E E or T | T T T and F | F F not F | ( E) | p | q
286
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法 S S and S | S or S | not S | p | q | (S) 非二义文法的产生式如下: E E or T | T T T and F | F F not E | ( E) | p | q ? not p and q有两种不同的最左推导
287
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法
例 题 1 下面的二义文法描述命题演算公式的语法, 为它写一个等价的非二义文法 S S and S | S or S | not S | p | q | (S) 非二义文法的产生式如下: E E or T | T not p and q T T and F | F not p and q F not E | ( E) | p | q ? not p and q有两种不同的最左推导
288
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合 二义文法: S a S b S | b S a S | aabbabab aabbabab S S S S
289
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合 二义文法: S a S b S | b S a S | aabbabab aabbabab 二义文法: S a B | b A | A a S | b A A B b S | a B B aabbabab aabbabab aabbabab B B B B B B
290
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合
例 题 2 设计一个文法:字母表{a, b}上a和b的个数相 等的所有串的集合 二义文法: S a S b S | b S a S | aabbabab aabbabab 二义文法: S a B | b A | A a S | b A A B b S | a B B aabbabab aabbabab aabbabab 非二义文法: S a B S | b A S | A a | b A A a abb abab B b | a B B a B S
291
例 题 3 试说明下面文法不是LR(1)的: L M L b | a M M b L a 句子abbb的分析树
292
例 题 4 下面的文法不是LR(1)的,对它略做修改,使之成为 一个等价的SLR(1)文法
例 题 4 下面的文法不是LR(1)的,对它略做修改,使之成为 一个等价的SLR(1)文法 program begin declist ; statement end declist d ; declist | d statement s ; statement | s 该文法产生的句子的形式是 begin d ; d ; … ; d ; s ; s ; … ; s end 修改后的文法如下: program begin declist statement end declist d ; declist | d ;
293
例 题 5 一个C语言的文件如下,第四行的if误写成fi: long gcd(p,q) long p,q; { fi (p%q == 0)
例 题 5 一个C语言的文件如下,第四行的if误写成fi: long gcd(p,q) long p,q; { fi (p%q == 0) return q; else return gcd(q, p%q); } 基于LALR(1)方法的一个编译器的报错情况如下: parse error before ‘return’ ( line 5). 是否违反了LR分析的活前缀性质?
294
习 题 第一次:3.2, 3.4(b)(c), 3.6(a)(b) 第二次:3.8 第三次:3.15 第四次:3.18(a)
习 题 第一次:3.2, 3.4(b)(c), 3.6(a)(b) 第二次:3.8 第三次:3.15 第四次:3.18(a) 第五次:3.21, 3.23 第六次:3.27, 3.31
Similar presentations