第三章 语法分析 本章内容 上下文无关文法 自上而下分析和自下而上分析 围绕分析器的自动生成展开 词 法 分析器 记 号 取下一个记号

Slides:



Advertisements
Similar presentations
說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
Advertisements

编 译 原 理 指导教师:杨建国 二零一零年三月.
第6章 LR分析程序及其自动构造 6.1 自下而上分析及其LR分析概述 6.2 LR (0) 分析 6.3 SLR(1) 分析
第二章 文法和语言 2.1 文法的基本概念 符号和符号串 2.2 句型的分析 文法和语言的形式定义 推导与递归 文法的分类 语法树
习题与试题 认真复习,重点是掌握基本概念。基本概念掌握了,相当一部分试题的解就有了
编 译 原 理 指导教师:杨建国 二零一零年三月.
常用逻辑用语复习课 李娟.
第2章 LR分 析 法 LR分析法是一种自下而上进行规范归约的语法分析方法,LR指“自左向右扫描和自下而上进行归约”。LR分析法比递归下降分析法、LL(1)分析法和算符优先分析法对文法的限制要少得多,对大多数用无二义的上下文无关文法描述的语言都可以用LR分析器予以识别,而且速度快,并能准确、及时地指出输入串的任何语法错误及出错位置。LR分析法的一个主要缺点是,若用手工构造分析器则工作量相当大,因此必须求助于自动产生LR分析器的产生器。
LR与LL分析 编译原理习题课二 胡云斌 PB
了解太平天国运动的主要史实,认识农民起义在民主革命时期的作用与局限性。
第三节 格林公式及其应用(2) 一、曲线积分与路径无关的定义 二、曲线积分与路径无关的条件 三、二元函数的全微分的求积 四、小结.
初中数学八年级下册 (苏科版) 10.4 探索三角形 相似的条件(2).
编译原理与技术 课程总结.
编译原理与技术 --文法和分析 2018/9/17 《编译原理与技术》讲义.
! 温故知新 上下文无关文法 最左推导 最右推导 自上而下 自下而上 句柄 归约 移进-归约冲突 移进-归约分析 递归下降预测分析
Chapter4 Syntax Analysis
编译原理 第一章 编译程序概述 第二章 PL/0编译程序的实现 第三章 文法和语言 第四章 词法分析 第五章 自顶向下语法分析方法
Part5语法分析 授课:胡静.
第四章 语法分析 赵建华 南京大学计算机系
编译原理复习.
编译原理与技术 第3章 语法分析 14学时.
编译原理习题
2.2 语法分析器生成器YACC 分析器的构造步骤: 产生式→识别活前缀的DFA→分析表(+驱动器) YACC概述
自上而下分析 4.4.
自上而下分析 4.4.
第6章 自底向上优先分析法 自底向上优先分析概述 简单优先分析 算符优先分析 返回目录.
第四章 语法分析.
第三章 词法分析.
Part5语法分析 授课:胡静.
第2次课 上下文无关文法
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
LL(1)分析方法 LL(1)是LL(k)的特例,其中的k则表示向前看k个符号. LL(1)方法和递归下降法属于同一级别的自顶向下分析法.
LL分析法 LL分析法的分析器由一张预测分析表(LL(1)分析表),一个控制程序(表驱动程序)及一分析栈组成 输入
第五章 语法分析——自下而上分析 自上而下分析法(Top-down) 自下而上分析法(Bottom-up) 国防科技大学计算机系602教研室.
《编译原理与技术》 期末复习 计算机科学与技术学院 郑启龙 李 诚 25/12/2018.
编译原理 第四章 语法分析—自上而下分析 编译原理.
第三章 语法分析 自顶向下语法分析思想 语法分析方法的分类: 自顶向下语法分析方法(Top-Down) ,亦称面向目标的分析方法;
语法分析 本章内容 语法分析器:把词法分析生成的词法单元流翻译成语法分析树(parse tree)
第五章 自底向上分析方法 LR(0)分析法.
第3,4次课 一个简单的语法制导翻译器 2.3~2.5.
LL(1)分析法 复 习 LL分析程序构造及分析过程 输入串 符号栈 执行程序 此过程有三部分组成: 分析表 执行程序 (总控程序)
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
第五章 自底向上分析方法 LR(0)分析法 1 LR(K)分析法 第一个L表示:相应的语法分析将按自左至右的顺序扫描输入符号串;
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
编译原理总结-1 第3~5章.
LALR(1)分析方法.
编译原理实践 13.语法分析程序的自动生成工具YACC.
第五章 语法分析-自下而上分析 5.1 自下而上分析的基本问题 Figure5.5LR演示自下而上分析 i+(i+i)*i
文法等价变换 文法的等价 对文法G1和G2,若有:L(G1)=L(G2),则称文法G1和G2等价, 记作:G1=G2. 文法等价变换
第四章 自顶向下语法分析方法 语法分析的主要工作:是识别由词法分析给出的单词 序列是否是给定的正确句子(程序)。
自底向上的语法分析 4.5.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第九节 赋值运算符和赋值表达式.
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
编译原理与技术 -- 自顶向下分析 2019/5/5 《编译原理与技术》讲义.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
第15讲 特征值与特征向量的性质 主要内容:特征值与特征向量的性质.
SLR(1)分析方法.
第四章 语法分析 南京大学计算机系 戴新宇
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第五章 语法分析—自下而上分析 自下而上分析法:即是从输入串开始,逐步进行 “归约”,直至归约到文法的开始符号;
编译原理 第五章 语法分析——自下而上分析 编译原理.
第四章 UNIX文件系统.
编译原理 第一章 编译程序概述 第二章 PL/0编译程序的实现 第三章 文法和语言 第四章 词法分析 第五章 自顶向下语法分析方法
§4.5 最大公因式的矩阵求法( Ⅱ ).
编译原理实践 6.程序设计语言PL/0.
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
编译原理 第一章 编译程序概述 第二章 PL/0编译程序的实现 第三章 文法和语言 第四章 词法分析 第五章 自顶向下语法分析方法
Presentation transcript:

第三章 语法分析 本章内容 上下文无关文法 自上而下分析和自下而上分析 围绕分析器的自动生成展开 词 法 分析器 记 号 取下一个记号 第三章 语法分析 词 法 分析器 记 号 取下一个记号 源程序 分析树 前端的 其余部分 中间表示 符号表 本章内容 上下文无关文法 自上而下分析和自下而上分析 围绕分析器的自动生成展开

3.1 上下文无关文法 3.1.1 上下文无关文法的定义 正规式能定义一些简单的语言,能表示给定结构的固定次数的重复或者没有指定次数的重复 例:a (ba)5, a (ba)* 正规式不能用于描述配对或嵌套的结构 例1:配对括号串的集合 例2:{wcw | w是a和b的串}

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  

3.1 上下文无关文法 简化表示 expr  expr op expr | (expr) |  expr | id op  + |  E  E A E | (E ) | E | id A  + | 

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

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)

3.1 上下文无关文法 3.1.3 分析树 例 E  E + E | E  E | (E ) |  E | id E  E ( E

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 两个不同的最左推导

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

3.2 语言和文法 文法的优点 文法的问题 文法给出了精确的,易于理解的语法说明 自动产生高效的分析器 可以给语言定义出层次结构 以文法为基础的语言的实现便于语言的修改 文法的问题 文法只能描述编程语言的大部分语法,不能描述语言中上下文有关的语法特征

3.2 语言和文法 3.2.1 正规式和上下文无关文法的比较 正规式 文法 (a|b)*ab A0  a A0 | b A0 | a A1 开始 a b

3.2 语言和文法 3.2.2 分离词法分析器理由 为什么要用正规式定义词法 词法规则非常简单,不必用上下文无关文法 对于词法记号,正规式描述简洁且易于理解 从正规式构造出的词法分析器效率高

3.2 语言和文法 从软件工程角度看,词法分析和语法分析的分离有如下好处 简化设计 编译器的效率会改进 编译器的可移植性加强 便于编译器前端的模块划分

3.2 语言和文法 能否把词法分析并入到语法分析中,直接从字符流进行语法分析 若把词法分析和语法分析合在一起,则必须将语言的注解和空白的规则反映在文法中,文法将大大复杂 注解和空白由自己来处理的分析器,比注解和空格已由词法分析器删除的分析器要复杂得多

3.2 语言和文法 3.2.3 验证文法产生的语言 G : S  (S) S |  L(G) = 配对的括号串的集合

3.2 语言和文法 3.2.3 验证文法产生的语言 G : S  (S) S |  L(G) = 配对的括号串的集合 按推导步数进行归纳:推出的是配对括号串 归纳基础: S   归纳假设:少于n步的推导都产生配对的括号串 归纳步骤:n步的最左推导如下: S  (S)S * (x) S * (x) y

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

3.2 语言和文法 3.2.4 适当的表达式文法 用一种层次观点看待表达式 id  id  (id+id) + id  id + id

3.2 语言和文法 3.2.4 适当的表达式文法 用一种层次观点看待表达式 id  id  (id+id) + id  id + id 3.2.4 适当的表达式文法 用一种层次观点看待表达式 id  id  (id+id) + id  id + id id  id  (id+id) 文法 expr  expr + term | term term  term  factor | factor factor  id | (expr)

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 分析树

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

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

3.2 语言和文法 3.2.6 消除左递归 文法左递归 A+Aa 直接左递归 AAa |b 消除直接左递归 A  b A 串的特点 ba . . . a 消除直接左递归 A  b A A a A | 

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  | 

3.2 语言和文法 非直接左递归 S  Aa | b A  Sd |  先变换成直接左递归 A  Aad | bd |  再消除左递归 A  bd A | A A  adA | 

3.2 语言和文法 3.2.7 提左因子 有左因子的文法 A 1 | 2 提左因子 A   A A  1 | 2

3.2 语言和文法 例 悬空else的文法 stmt  if expr then stmt else stmt | other 提左因子 stmt  if expr then stmt optional_else_part optional_else_part  else stmt | 

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个下划线键

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

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的路径

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 短语文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 短语文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 短语文法、上下文有关文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 2型文法:A  ,AVN ,   (VN ∪VT)* 短语文法、上下文有关文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 2型文法:A  ,AVN ,   (VN ∪VT)* 短语文法、上下文有关文法、上下文无关文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 2型文法:A  ,AVN ,   (VN ∪VT)* 3型文法:A  aB或A  a,A, BVN , a VT 短语文法、上下文有关文法、上下文无关文法

3.2 语言和文法 3.2.9 形式语言鸟瞰 文法 G = (VT , VN, S, P) 0型文法:  , ,   (VN VT)*, | |  1 1型文法:| |  | |,但S  可以例外 2型文法:A  ,AVN ,   (VN ∪VT)* 3型文法:A  aB或A  a,A, BVN , a VT 短语文法、上下文有关文法、上下文无关文法、正规文法

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)n1 用S  aSBC n-1次 S + an(BC)n 用S  aBC 1次 S + anBnCn 用CB  BC交换相邻的CB S + anbBn1Cn 用aB  ab 1次 S + anbnCn 用bB  bb n-1次 S + anbncCn-1 用bC  bc 1次 S + anbncn 用cC  cc n-1次

3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S  aCb C  cd | c 为输入串w = acb建立分析树 不能处理左递归

3.3 自上而下分析 不能处理左递归的例子 算术表达文法 E  E + T | T T  T  F | F F  ( E ) | id E E + T E + T E + T … … …

3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S  aCb C  cd | c 为输入串w = acb建立分析树 不能处理左递归、复杂的回溯技术

3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S  aCb C  cd | c 为输入串w = acb建立分析树 不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来

3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S  aCb C  cd | c 为输入串w = acb建立分析树 不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来、难以报告出错的确切位置

3.3 自上而下分析 3.3.1 自上而下分析的一般方法 例 文法 S  aCb C  cd | c 为输入串w = acb建立分析树 不能处理左递归、复杂的回溯技术、回溯导致语义工作推倒重来、难以报告出错的确切位置、效率低

3.3 自上而下分析 3.3.2 LL(1)文法 对文法加什么样的限制可以保证没有回溯? 先定义两个和文法有关的函数 FIRST( ) = {a |  * a…, a  VT} 特别是, * 时,规定  FIRST( ) 对A的任何两个不同选择i 和j,希望有 FIRST(i )  FIRST(j ) =  若FIRST(i ) 或 FIRST(j )含,还需增加条件

3.3 自上而下分析 3.3.2 LL(1)文法 对文法加什么样的限制可以保证没有回溯? 先定义两个和文法有关的函数 FIRST( ) = {a |  * a…, a  VT} 特别是, * 时,规定  FIRST( ) FOLLOW(A) = {a | S * …Aa…,aVT} 如果A是某个句型的最右符号,那么$属于FOLLOW(A)

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  …

3.3 自上而下分析 LL(1)文法 任何两个产生式A  |  都满足下列条件: LL(1)文法有一些明显的性质 FIRST( )  FIRST( ) =  若 *  ,那么FIRST()  FOLLOW(A) =  LL(1)文法有一些明显的性质 没有公共左因子 不是二义的 不含左递归

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) 中。

3.3 自上而下分析 3.3.3 递归下降的预测分析 例 type  simple |  id 为每一个非终结符写一个分析过程 这些过程可能是递归的 例 type  simple |  id | array [simple] of type simple  integer | char | num dotdot num

3.3 自上而下分析 一个辅助过程 void match (terminal t) { if (lookahead == t) lookahead = nextToken( ); else error( ); }

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

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

3.3 自上而下分析 3.3.4 非递归的预测分析 a + b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈

3.3 自上而下分析 分析表的一部分 非终 结符 输 入 符 号 id +  . . . E E  TE  E  输 入 符 号 id +  . . . E E  TE  E  E   +TE  T T  FT  T  T    T   FT  F F  id

3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id  id + id$

3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id  id + id$ 输 入 输 出 $E id  id + id$ $E T E  TE 

3.3 自上而下分析 预测分析器接受输入id * id + id的前一部分动作 栈 输 入 输 出 $E id  id + id$ 输 入 输 出 $E id  id + id$ $E T E  TE  $E T F T  FT 

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

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$

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 

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$

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$

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

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

3.3 自上而下分析 消去多重定义 非终 结符 输 入 符 号 other b else . . . stmt stmt  other 输 入 符 号 other b else . . . stmt stmt  other e_part e_part else stmt expr expr  b

3.3 自上而下分析 3.3.6 预测分析的错误恢复 1、先对编译器的错误处理做一个概述 词法错误,如标识符、关键字或算符的拼写错 语法错误,如算术表达式的括号不配对 语义错误,如算符作用于不相容的运算对象 逻辑错误,如无穷的递归调用

3.3 自上而下分析 2、分析器对错误处理的基本目标 清楚而准确地报告错误的出现,并尽量少出现伪错误 迅速地从每个错误中恢复过来,以便诊断后面的错误 它不应该使正确程序的处理速度降低太多

3.3 自上而下分析 3、非递归预测分析在什么场合下发现错误 输入 预测分析程序 输出 栈 分析表M 栈顶的终结符和下一个输入符号不匹配 a + b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈

3.3 自上而下分析 3、非递归预测分析在什么场合下发现错误 输入 预测分析程序 输出 栈 分析表M 栈顶是非终结符A,输入符号是a,而M[A , a]是空白 a + b $ 输入 预测分析程序 分析表M 输出 X Y Z 栈

3.3 自上而下分析 4、非递归预测分析:采用紧急方式的错误恢复 5、同步 发现错误时,分析器每次抛弃一个输入记号,直到输入记号属于某个指定的同步记号集合为止 5、同步 词法分析器当前提供的记号流能够构成的语法构造,正是语法分析器所期望的 不同步的例子 语法分析器期望剩余的前缀构成过程调用语句,而实际剩余的前缀形成赋值语句

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 if expr then stmt (then和分号等记号是expr的同步记号)

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 把高层构造的开始符号加到低层构造的同步记号集合中

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 把高层构造的开始符号加到低层构造的同步记号集合中 a = expr; if … (语句的开始符号作为表达式的同步记号,以免表达式出错又遗漏分号时忽略if语句等一大段程序)

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 把高层构造的开始符号加到低层构造的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 a = expr; , if … (语句的开始符号作为语句的同步符号,以免多出一个逗号时会把if语句忽略了)

3.3 自上而下分析 6、同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 把高层构造的开始符号加到低层构造的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 如果非终结符可以产生空串,若出错时栈顶是这样的非终结符,则可以使用推出空串的产生式

3.3 自上而下分析 例 栈顶为T ,面临id时出错 非终 结符 输 入 符 号 id +  . . . E ETE E 输 入 符 号 id +  . . . E ETE E E+TE T TFT  T  出错 T   T FT 

3.3 自上而下分析 T 可以产生空串,报错并用T  非终 结符 输 入 符 号 id +  . . . E ETE E 输 入 符 号 id +  . . . E ETE E E+TE T TFT  T  出错, 用T   T   T FT 

3.3 自上而下分析 同步记号集合的选择 把FOLLOW(A)的所有终结符放入非终结符A的同步记号集合 把高层结构的开始符号加到低层结构的同步记号集合中 把FIRST(A)的终结符加入A的同步记号集合 如果非终结符可以产生空串,若出错时栈顶是这样的非终结符,则可以使用推出空串的产生式 如果终结符在栈顶而不能匹配,弹出此终结符

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde(读入ab) a b

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde(归约) a A

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde(再读入bc)

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde aAde(归约) a b A c

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde aAde(再读入d) a b A d c

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde aAde

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde aAde aABe(再读入e) e a b A d c B

3.4 自下而上分析 3.4.1 归约 例 S  aABe A  Abc | b B  d abbcde aAbcde aAde

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

3.4 自下而上分析 3.4.2 句柄 句型的句柄是和某产生式右部匹配的子串,并且,把它归约成该产生式左部的非终结符代表了最右推导过程的逆过程的一步 S  aABe A  Abc | b B  d S rm aABe rm aAde rm aAbcde rm abbcde 句柄的右边仅含终结符 如果文法二义,那么句柄可能不唯一

3.4 自下而上分析 例 句柄不唯一 E  E + E | E  E | (E ) | id

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

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中,句柄不唯一

3.4 自下而上分析 3.4.3 用栈实现移进归约分析 先通过 来了解移进归约分析的工作方式 移进归约分析器在分析输入串id1  id2 + id3时的动作序列 来了解移进归约分析的工作方式

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E  E+E归约

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E  E+E归约

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E  E+E归约 按E  EE归约

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E  E+E归约 按E  EE归约

3.4 自下而上分析 栈 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 输 入 动 作 $ id1  id2 + id3$ 移进 $ id1  id2 + id3$ 按E  id归约 $E $E id2 + id3$ $Eid2 + id3$ $EE $EE+ id3$ $EE+id3 $EE+E 按E  E+E归约 按E  EE归约 接受

3.4 自下而上分析 要想很好地使用移进归约方式,尚需解决一些问题 如何决策选择移进还是归约 进行归约时,确定右句型中将要归约的子串 进行归约时,如何确定选择哪一个产生式

3.4 自下而上分析 3.4.4 移进归约分析的冲突 1、移进归约冲突 例 stmt  if expr then stmt | if expr then stmt else stmt | other 如果移进归约分析器处于格局 栈 输入 … if expr then stmt else … $

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 ?

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 )… 需要修改上面的文法

3.5 LR分析器 本节介绍LR(k)分析技术 特点 主要介绍构造LR分析表的三种技术 适用于一大类上下文无关文法 效率高 简单的LR方法(简称SLR) 规范的LR方法 向前看的LR方法(简称LALR)

3.5 LR分析器 3.5.1 LR分析算法 输入 LR分析程序 输出 栈 LR分析器的模型 action goto sm Xm Xm-1 … s0 a1 ai an $

3.5 LR分析器 例 E  E + T | E  T T  T  F | T  E F  (E ) | F  id 状态 动 作 转 移 id +  ( ) $ E T F s5 s4 1 2 3 1 s6 acc 2 r2 s7 r2 r2 3 r4 r4 r4 r4 4 8 2 3

3.5 LR分析器 栈 输 入 动 作 id  id + id $

3.5 LR分析器 栈 输 入 动 作 id  id + id $ 移进

3.5 LR分析器 栈 输 入 动 作 id  id + id $ 移进 0 id 5  id + id $

3.5 LR分析器 栈 输 入 动 作 id  id + id $ 移进 0 id 5  id + id $ 按F  id归约

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

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归约

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

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

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 $

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 $

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 $

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 $

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

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  TF归约

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  TF归约 . . .

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  TF归约 . . . 0 E 1 $

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  TF归约 . . . 0 E 1 $ 接受

3.5 LR分析器 3.5.2 LR文法和LR分析方法的特点 1、概念 活前缀:右句型的前缀,该前缀不超过最右句柄的右端 S *rm  A w rm   w  的任何前缀(包括和 本身)都是活前缀

3.5 LR分析器 3.5.2 LR文法和LR分析方法的特点 1、概念 活前缀:右句型的前缀,该前缀不超过最右句柄的右端 2、定义

3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀

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  TF归约 . . . 0 E 1 $ 接受

3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA

3.5 LR分析器 例 E  E + T | E  T 下表绿色部分构成 T  T  F | T  E 识别活前缀DFA的 F  (E ) | F  id 状态转换表 状态 动 作 转 移 id +  ( ) $ E T F s5 s4 1 2 3 1 s6 acc 2 r2 s7 r2 r2 3 r4 r4 r4 r4 4 8 2 3

3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA 栈顶的状态符号包含了确定句柄所需要的一切信息

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  TF归约 . . . 0 E 1 $ 接受

3.5 LR分析器 3、LR分析方法的特点 栈中的文法符号总是形成一个活前缀 分析表的转移函数本质上是识别活前缀的DFA 栈顶的状态符号包含了确定句柄所需要的一切信息 是已知的最一般的无回溯的移进归约方法 能分析的文法类是预测分析法能分析的文法类的真超集 能及时发现语法错误 手工构造分析表的工作量太大

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上 自 上 而 下

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上 自 上 而 下 归约还是推导 规 范 归 约 最 左 推 导

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 在下面的推导中,最后一步用的是A l S rm …  rm  A b w  rm  l  b w LR(1)决定用该 产生式的位置 LL(1)决定用该 产生式的位置

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 建立分析树的方式 自 下 而 上 自 上 而 下 归约还是推导 规 范 归 约 最 左 推 导 决定使用产生式的时机 看见产生式右部推出的整个终结符串后,才确定用哪个产生式进行归约 看见产生式右部推出的第一个终结符后,便要确定用哪个产生式推导

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制 无左递归、无公共左因子

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制 无左递归、无公共左因子 分析表比较 状态×文法符号 分析表大 非终结符×终结符 分析表小

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 对文法的显式限制 对文法没有限制 无左递归、无公共左因子 分析表比较 状态×文法符号 分析表大 非终结符×终结符 分析表小 分析栈比较 状态栈,通常状态比文法符号包含更多信息 文法符号栈

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 确定句柄 根据栈顶状态和下一个符号便可以确定句柄和归约所用产生式 无句柄概念

3.5 LR分析器 4、LR分析方法和LL分析方法的比较 LR(1)方 法 LL(1)方 法 确定句柄 根据栈顶状态和下一个符号便可以确定句柄和归约所用产生式 无句柄概念 语法错误 决不会将出错点后的符号移入分析栈 和LR一样,决不会读过出错点而不报错

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态 expr + term 

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态 expr + term * factor 

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态 expr + term * factor 

3.5 LR分析器 3.5.3 构造SLR分析表 术语:LR(0)项目(简称项目) 例 AXYZ对应有四个项目 在右部的某个地方加点的产生式 加点的目的是用来表示分析过程中的状态 例 AXYZ对应有四个项目 A  ·XYZ A  X·YZ A  XY·Z A  XYZ· 例 A 只有一个项目和它对应 A  ·

3.5 LR分析器 构造SLR分析表的两大步骤 1、从文法构造识别活前缀的DFA 2、从上述DFA构造分析表

3.5 LR分析器 1、从文法构造识别活前缀的DFA 1)拓广文法 E  E + T | T T T  F | F F ( E ) | id

3.5 LR分析器 1、从文法构造识别活前缀的DFA 1)拓广文法 E   E E  E + T | T T T  F | F F ( E ) | id

3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E

3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E  ·E + T

3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E  ·E + T T  ·T  F T  ·F

3.5 LR分析器 1、从文法构造识别活前缀的DFA 2)构造LR(0)项目集规范族 I0: E ·E E  ·E + T T  ·T  F T  ·F F  ·(E) F  ·id

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

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

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

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

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

3.5 LR分析器 I0: I4: E ·E F  (·E ) ( E  ·E + T E  ·T T  ·T  F F  ·id (

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 (

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

3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id

3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I1: E  E· E  E·+ T

3.5 LR分析器 I1: E  E· E  E·+ T I6 : EE + ·T T ·T  F T ·F + ( id I1: E  E· E  E·+ T I6 : EE + ·T T ·T  F T ·F F ·(E) F ·id +

3.5 LR分析器 I1: I2: E  E· ET· E  E·+ T TT·F I6 : EE + ·T ( id I1: I2: E  E· ET· E  E·+ T TT·F I6 : EE + ·T T ·T  F T ·F F ·(E) F ·id +

3.5 LR分析器  I1: I2: E  E· ET· E  E·+ T TT·F I6 : I7: ( id I1: I2: E  E· ET· E  E·+ T TT·F I6 : I7: EE + ·T TT·F T ·T  F F ·(E) T ·F F ·id F ·(E) F ·id + 

3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I3: T  F· 无状态转换

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

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

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 ET· F  ·( E ) TT·F F  ·id E T

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 ET· F  ·( E ) TT·F F  ·id I3: TF· E T F

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 ET· F  ·( E ) TT·F F  ·id I3: TF· I4: F (·E ) . . . E T F (

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 ET· F  ·( E ) TT·F F  ·id I3: TF· I4: I5: F (·E ) F id· . . . E T F ( id

3.5 LR分析器 I1 I0 E I3 I2 I4 I5 T F ( id I5: F id· 无状态转换

3.5 LR分析器 I1 I0 + E I6 I3 I2 I4 I8 I7 I5 指向I2 指向I3 T * F ( id

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 的所有前缀都可接受

3.5 LR分析器 也可以构造一个识别活前缀的NFA N I0: E  ·E E  ·E + T E  ·T T  ·T  F F  ·(E) F  ·id

3.5 LR分析器 也可以构造一个识别活前缀的NFA N 每个项目一个状态 I0: E  ·E E  ·E E  ·E + T T  ·T  F T  ·F F  ·(E) F  ·id

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  

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    

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      

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        

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          

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          

3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目 如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 E  ·E+T对  和 ( 这两个活前缀都有效 E  E E+T (,1都为空) E  E  (E)  (E+T) ( =“(”,1为空) 该DFA读过 和(后到达不同的状态,那么项目 E  · E+T就出现在对应的不同项目集中

3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目 如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 从项目A1·2对活前缀1有效这个事实可以知道 如果2  ,应该移进 如果2=, 应该用产生式A1归约

3.5 LR分析器 从文法构造的识别活前缀的DFA的一些特点 概念:有效项目 如果S*rm Aw rm 12w,那么就说项目A1·2对活前缀1是有效的 (1)一个项目可能对好几个活前缀都是有效的 (2)一个活前缀可能有多个有效项目 一个活前缀的有效项目集就是从这个DFA的初态出发,沿着标记为的路径到达的那个项目集(状态)

3.5 LR分析器 例 串E + T 是活前缀,读完它后,DFA处于状态I7 I7: TT  ·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

3.5 LR分析器 构造SLR分析表的两大步骤 1、从文法构造识别活前缀的DFA 2、从上述DFA构造分析表

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的编号 如果[SS·]在Ii中,那么置action[ i, $ ]为接受acc 如果出现动作冲突,那么该文法就不是SLR(1) 的

3.5 LR分析器 2、从DFA构造SLR分析表 状态i从Ii构造,它的action函数如下确定: 使用下面规则构造状态i的goto函数: . . . 使用下面规则构造状态i的goto函数: 对所有的非终结符A,如果goto(Ii, A) = Ij, 那么goto[i, A] = j

3.5 LR分析器 2、从DFA构造SLR分析表 状态i从Ii构造,它的action函数如下确定: 使用下面规则构造状态i的goto函数: . . . 使用下面规则构造状态i的goto函数: 不能由上面两步定义的条目都置为error 分析器的初始状态是包含[S·S]的项目集对应的状态

3.5 LR分析器 例 I2: E  T· T  T·  F 因为FOLLOW(E) = {$, +, )}, 所以 action[2, $]=action[2, +]=action[2, )]=r2 action[2, ] = s7

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, = ]为按 EV归约,因为=是 E的一个后继符 =是E的一个后继符: S $ V = E $   E = E $

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, = ]为按 EV归约,因为=是 E的一个后继符 在所关注场合E的后继是$: S $ V = E $   E = E $ S $ E $  V $

3.5 LR分析器 3.5.4 构造规范的LR分析表 LR(1)项目: 重新定义项目,让它带上搜索符,成为如下形式 [A ·, a] LR(1)项目[A ·, a]对活前缀有效: 如果存在着推导S *rm Aw rm w,其中:  = ; a是w的第一个符号,或者w是且a是$

3.5 LR分析器 例 S  BB B  bB | a 从最右推导S *rm bbBba rm bbbBba看出: [Bb·B, b]对活前缀 = bbb是有效的 对于项目[A ·, a],当为空时,是根据搜索符a来填表(归约项目),而不是根据A的后继符来填表

3.5 LR分析器 S ·S, $ I0 S ·BB, $ B ·bB, b/a B ·a, b/a

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

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

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 如果[SS·, $]在Ii中,那么置action[i, $] = acc 如果用上面规则构造出现了冲突,那么文法就不是LR(1)的

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

3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA (2)从Ii构造分析器的状态i, 状态i的action函数如下确定 . . . (3) 状态i的goto函数如下确定: (4) 用上面规则未能定义的所有条目都置为error

3.5 LR分析器 构造规范的LR分析表 (1) 基于LR(1)项目来构造识别G活前缀的DFA (2)从Ii构造分析器的状态i, 状态i的action函数如下确定 . . . (3) 状态i的goto函数如下确定: (4) 用上面规则未能定义的所有条目都置为error (5) 分析器的初始状态是包含[S·S, $]的项目集对应的状态

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

3.5 LR分析器 3.5.5 构造LALR分析表 研究LALR的原因 LALR特点 LALR分析表构造方法 规范LR分析表的状态数偏多 LALR和SLR的分析表有同样多的状态,比规范LR分析表要小得多 LALR的能力介于SLR和规范LR之间 LALR的能力在很多情况下已经够用 LALR分析表构造方法 通过合并规范LR(1)项目集来得到

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仅搜索符不一样

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合并

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$

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$

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 有三组同心集,都合并

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

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 栈 输入 0 bba$

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 栈 输入 0b36 ba$

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 栈 输入 0b36b36 a$

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 栈 输入 0b36b36a47 $

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 栈 输入 0b36b36B89 $

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 栈 输入 0b36B89 $

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 栈 输入 0B2 $ 报错

3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心的LR(1)项目集: 略去搜索符后它们是相同的集合

3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心集的合并不会引起新的移进归约冲突 项目集1 项目集2 项目集1 项目集2 [A ·, a] [B·a, b] . . . . . . 若合并后有冲突

3.5 LR分析器 1、合并同心项目集可能会引起冲突 同心集的合并不会引起新的移进归约冲突 项目集1 项目集2 项目集1 项目集2 [A ·, a] [B·a, b] [B·a, c] [A ·, d] . . . . . . 则合并前就有冲突

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

3.5 LR分析器 2、构造LALR(1)分析表 (1) 构造LR(1)项目集规范族C = {I0, I1, …, In}

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

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

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

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

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

3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 例 二义文法 E  E + E | E  E | (E) | id 非二义的文法: E E + T | T T T  F | F F  (E) | id 该文法有单个非终结符为右部的产生式

3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 可以用文法以外的信息来消除二义 3.6 二义文法的应用 二义文法的特点: 二义文法决不是LR文法 简洁、自然 可以用文法以外的信息来消除二义 语法分析的效率高(基于消除二义后得到的分析表)

3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 3.6 二义文法的应用 3.6.1 使用文法以外信息来解决分析动作冲突 例 二义文法 E  E + E | E  E | (E) | id 规定: 优先级高于+,两者都是左结合

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

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 面临+,归约

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 面临+,归约 面临,移进

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 面临+,归约 面临,移进 面临 ) 和$,归约

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

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 面临+,归约

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 面临+,归约 面临,归约

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 面临+,归约 面临,归约 面临 ) 和$,归约

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

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 从定义形式语言的角度说,第一个产生式是多余的

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 联系到语义处理,第一个产生式是必要的

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,需要下面第一种输出

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 按前面一个产生式归约

3.6 二义文法的应用 3.6.3 LR分析的错误恢复 1、LR分析器在什么情况下发现错误 访问动作表时若遇到出错条目 3.6 二义文法的应用 3.6.3 LR分析的错误恢复 1、LR分析器在什么情况下发现错误 访问动作表时若遇到出错条目 访问转移表时它决不会遇到出错条目 决不会把不正确的后继移进栈 规范的LR分析器甚至在报告错误之前决不做任何无效归约

3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 . . . . . . . . a . . A 发现错误 s : C ·A 3.6 二义文法的应用 2、紧急方式错误恢复 s . 栈 . . . . . . . . a . . A 发现错误 s : C ·A A· b . . . s1 : C A· Ab· b

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· Ab· b

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· Ab· b

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· Ab· b

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 输入 输出

3.7 分析器的生成器 3.7.2 用Yacc处理二义文法 例 简单计算器 输入一个表达式并回车,显示计算结果 也可以输入一个空白行

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 %%

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 %%

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? 取后者

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

3.7 分析器的生成器 3.7.3 Yacc的错误恢复 编译器设计者的工作 Yacc把错误产生式当作普通产生式处理 3.7 分析器的生成器 3.7.3 Yacc的错误恢复 编译器设计者的工作 决定哪些“主要的”非终结符将有错误恢复与它们相关联 为各主要非终结符A加入形式为A  error 的错误产生式,其中是文法符号串 为这样的产生式配上语义动作 Yacc把错误产生式当作普通产生式处理

3.7 分析器的生成器 遇到语法错误时 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2 3.7 分析器的生成器 遇到语法错误时 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2 A ·error  . . . s1 : C1A·2 s2 : A error· error 

3.7 分析器的生成器 遇到语法错误时 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2 3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 s . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2 A ·error  . . . s1 : C1A·2 s2 : A error· error 

3.7 分析器的生成器 遇到语法错误时 s s2 . 栈 . . . . . . . . . . . A 发现错误 s : 3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 s s2 . 栈 . . . . . . . . . . . A 发现错误 s : C 1·A2 A ·error  . . . s1 : C1A·2 s2 : A error· error 

3.7 分析器的生成器 遇到语法错误时 栈 . . . . . . . . . . . A s : C 1·A2 3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 忽略若干输入符号,直至找到,把移进栈 栈 . . . . . . . . . . . A s : C 1·A2 A ·error  . . . s1 : C1A·2 s2 : A error· error  s s2 .

3.7 分析器的生成器 遇到语法错误时 s s1 . 栈 . . . . . . . . . . . A s : C 1·A2 3.7 分析器的生成器 遇到语法错误时 从栈中弹出状态,直到发现栈顶状态的项目集包含形为A ·error 的项目为止 把虚构的终结符error“移进”栈 忽略若干输入符号,直至找到,把移进栈 把error 归约为A,恢复正常分析 s s1 . 栈 . . . . . . . . . . . A s : C 1·A2 A ·error  . . . s1 : C1A·2 s2 : A error· error 

3.7 分析器的生成器 增加错误恢复的简单计算器 lines : lines expr ‘\n’ {printf ( “%g \n”, $2 ) } | lines ‘\n’ | /  / | error ‘\n’{yyerror ( “重新输入上一行”); yyerrok;} ;

本 章 要 点 文法和语言的基本知识 自上而下的分析方法:预测分析,非递归的预测分析,LL(1)文法 本 章 要 点 文法和语言的基本知识 自上而下的分析方法:预测分析,非递归的预测分析,LL(1)文法 自下而上的分析方法:SLR(1)方法,规范LR(1)方法和LALR(1)方法 LR方法如何用于二义文法 语法分析的错误恢复方法

例 题 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

例 题 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有两种不同的最左推导

例 题 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有两种不同的最左推导

例 题 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

例 题 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

例 题 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

例 题 3 试说明下面文法不是LR(1)的: L  M L b | a M   M b L a  句子abbb的分析树

例 题 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 ;

例 题 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分析的活前缀性质?

习 题 第一次: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