编译原理简明教程(第2版)[冯秀芳,崔冬华,段富][电子教案] 第12章
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
12.1.2 错误的种类
改错及校正,指编译程序在其翻译过程中发 现源程序的错误时能适当地对源程序进行修 正。为了正确地校正错误,必须十分清楚地 了解程序的意图,了解错误的性质,并确切 地对错误定位。即使是词法错误,也必须根 据上下文,试探性地做出修改。
Biblioteka Baidu 12.1.2 错误的种类
一般来说,一个编译程序如果能在一次编译 时刻查出源程序中几乎所有的错误,指出错 误的性质,并给出错误所在的确切位置,对 于源程序的迅速改正将有很大的帮助。
12.1.2 错误的种类
一个源程序中的错误一般有如下四类。 ① 词法错误。编译程序在词法分析阶段发现 的源程序错误,例如,字符号(关键字)拼写有 错,标点符号有错,等等。 ② 语法错误。编译程序在语法分析阶段发现 的源程序错误,亦即书写不符合某语法成分的 语法规则。例如,作为语句括号的BEGIN与END 不匹配,“{”与“}”不匹配,以及IF与ELSE 之间缺少THEN,等等。另外,变量未说明或重 定义等也可看做语法错误。
12.1.1 错误存在的必然性
一个素质较好的程序员,在他交付的程序中 错误率为1%,即每100个语句中约含1条错误, 而水平低的程序员编写的程序,在刚开始调试 时错误率是很高的。错误产生原因大致是因为 问题(算法)的复杂性、程序员素质、输入错误 以及对系统环境不够了解等,概括起来是因为 人类自身能力的局限性。
12.1.3 错误复原
在错误复原时,应重视以下两个方面: 株连信息的遏止。 重复信息的遏止。 株连信息指的是因为源程序中的某个错误而导致编 译程序向用户发出的出错信息,该出错信息往往不 是真实的。
12.1.3 错误复原
例如,假定过程语句P(a,b)在输入时成了 p(a.b),编译时,编译程序将发出出错信息: 是不合法符号。如果做出的处理是删除,那么 ,当扫描p之后,将发出出错信息:缺少运算 符,当扫描到“)”时,将再发出出错信息: 参数个数少。显然后面两个出错信息是不真实 的。有时可能因为源程序中的一个错误而引出 一连串株连信息。应该遏止这种株连信息。 为了遏止株连错误,往往需要查看出错处的上 下文和取得相关的信息。例如,对于上述例子 ,可以取得关于过程p参数个数的信息,标识 符a是否记录类型信息,并向前查看到“)”确 定参数的个数。这样,甚至可以做出正确的修 改:把“· ”改成“,”。
12.2.2 词法错误的校正
② 如果某个标识符拼写有错,因此查找符号
表时不能查到相应条目,这时可用符号表中与 之最接近的标识符去代替它,例如,如果有语 句X: = sim(a),但不能在符号表中查到标识 符sim,则可以用最接近的sin去代替sim。 ③ 其他拼写错误的情况,例如,源程序中所 引用之下标变量的数组标识符因拼写错误而不 能在符号表中查到,控制转移语句的转移目标 (标号)因拼写错误而无定义,等等,都可以用 与上面类似的办法来校正。 一般地,可以用试探法,试验删除、插入、替 换和交换四种情况,以最可能成功的那种修改 作为对错误的校正。
12.2.1 词法错误的种类
对于错误复原问题,自然地涉及下列问题: 错误的查出。 错误的定位。 错误的局部化。 重复错误信息的遏止。 由于每一类单词可用一个正则表达式来描述, 所以在识别单词时,通常采用最长子串匹配策 略。
基于前面对词法错误的假设,不存在连续几个字符 都出错的现象,对词法错误的校正一般地有 删除一个字符。 插入一个字符。 替换一个字符。 交换相邻两个字符。
12.1.2 错误的种类
③ 语义错误。源程序中的语义错误有两类,一
类是在编译时才可发现的静态语义错误,例如 ,编译程序语义分析时发现的运算符对运算分 量类型而言不合法,或者双目运算符的两个运 算分量类型不相容,等等。另一类是在目标代 码运行时刻才能发现的动态语义错误,也就是 说,虽然编译程序把源程序翻译成了等价的目 标代码,未发现任何错误,但运行不能正常结 束或者运行结果经验证却是不正确的。
12.3.1 语法错误的复原
有的编译程序,对语法错误复原采取的措施是 简单地放过相应的语法结构,例如,放过一个 语句的后继符号等。这种过于简单的做法往往 失去发现更多语法错误的机会。更合适的是设 法进行校正,尽管这种校正不能保证总是成功 的,然而,关于校正的信息可供用户(程序书 写人员)参考。
12.1.3 错误复原
重复信息是因为源程序中的一个错误反映在源程序 中多处而产生的。一个典型的例子是标识符未说明 。如果一个标识符i未在某个过程说明的过程分程序 中说明,那么,在过程分程序的语句部分中每次引 用i时都将发出出错信息:标识符i无定义。
12.1.3 错误复原
为了遏止重复信息,可事先设立一个出错信息表, 其中给出一切可能的出错信息(性质)和编号,而编 译时刻,则建立一个出错信息集合,其元素呈(编号 、关联信息)形式。每当发现一个错误,便把相应的 (编号、关联信息)添加入该出错信息集合中。最后 ,编译结束时,把出错信息集合中的元素按某种次 序输出,便得到了无重复的一切出错信息。
12.1.2 错误的种类
对于一个好的编译程序来说,应能具有较强 的查错和改错能力。查错,就是编译程序能 在编译时刻,准确而及时地发现源程序中的 错误,并能以简明的方式向用户报告这些错 误的性质和出现的确切位置。一个编译程序 应在一次编译期间发现源程序中尽可能多的 错误,不是发现一个错误便立即停止编译。 在编译时刻能够查出的源程序的错误称为静 态错误,运行时刻才能查出的错误称为动态 错误。本章讨论的程序错误的检查和校正主 要是针对静态错误,即词法错误、语法错误 、非逻辑的或算法上的语义错误及违反环境 限制错误。
12.2.2 词法错误的校正
12.2.2 词法错误的校正
由于词法分析时,还不能收集到足够的信息,发现错 误便立即校正是不太恰当的,只是在某些场合可以予 以校正,下面列举若干。 ① 知道下一步应处理的字符号(关键字),而当前所扫 视的余留输入字符序列的任何前缀都不能构成字符号( 关键字),则可查字符号(关键字)表,从其中选择与当 前所扫视的输入字符串前缀最接近的字符号(关键字) 去代替这个前缀。例如“IF b THEM„”,对于 “THEM”将用最接近的“THEN”去代替。
《编译原理简明教程》
普通高等教育“十二五”规划计算机教材
---太原理工大学 ---计算机科学与技术学院 ---冯秀芳、崔冬华、段富等
目 录
•第一章 引言 •第二章 形式语言理论基础 •第三章 自动机理论基础 •第四章 词法分析 •第五章 语法分析—自顶向下分析方法 •第六章 语法分析—自底向上分析方法 •第七章 语义分析及中间代码的生成 •第八章 代码优化 •第九章 目标代码的生成 •第十章 符号表 •第十一章 目标程序运行时的存储组织与分配 •第十二章 出错处理 •第十三章 编译程序自动生成工具简介 •第十四章 面向对象语言的编译 •第十五章 并行编译技术
12.3 校正语法错误
12.3.1 语法错误的复原 12.3.2 语法错误的校正
12.3.1 语法错误的复原
对于语法错误的复原,与词法错误的情况一样,自 然地涉及下列问题: 错误的查出。 错误的定位。 错误的局部化。
重复错误信息的遏止。
12.3.1 语法错误的复原
12.3.2 语法错误的校正
1.自顶向下分析中错误的校正 假定在自顶向下分析过程中的某一时刻,源程序符 号串可写为w1Aw2的形式,其中,w1是已扫描部分 ,A是当前扫描符号,而w2是输入符号串的其余部 分。如果扫描到A时发现错误,分析程序又无法确 定下一个合法的分析动作,换言之,已构造的语法 树部分可覆盖w1,但不能继续构造语法树去覆盖A 与其余部分w2。
第12章 出错处理
12.1 引言 12.2 校正词法错误 12.3 校正语法错误 12.4 校正语义错误 习题12
12.1 引言
12.1.1 错误存在的必然性 12.1.2 错误的种类 12.1.3 错误复原
12.1.1 错误存在的必然性
编译程序用来对源程序进行编译,当程序在 语法(包括词法)上正确时,可以得到相应的等 价的目标代码。当程序在语义上正确时,以正 确的输入数据运行目标代码可以得到预期的输 出结果。然而,一个程序,尤其是大型软件的 程序,其中难免包含错误。一个软件开发中所 存在的错误分布比例大致为:56%的错误源自 需求分析,27%的错误源自设计,7%的错误源 自编码。有人认为“没有一个程序第一次运行 就能正确地工作”是计算机程序设计的一个公 理。
12.1.3 错误复原
下面再考虑遏止株连错误的另一个例子。假定对于 下标变量A[e1, e2, e3],发现标识符A不是数组名 ,扫描到“[”时发出出错信息:[错。此后显然将 发出一连串株连错误信息。究其原因,可能是因为 标识符A未被说明。为了遏止株连信息,可以这样处 理:用一个“万能”标识符U去代替有错的标识符A ,或者说让A可以与任意类型的数据结构相关联,这 时在符号表的相应条目中已加标志,且填入了数组 和维数的信息,只要其后形如[e1, e2, e3]出现, 将不再发出出错信息。
12.2 校正词法错误
12.2.1 词法错误的种类 12.2.2 词法错误的校正
12.2.1 词法错误的种类
词法分析程序的基本任务是读入源程序字符 序列,识别出具有独立意义的最小语法单位( 单词或符号),并把它们变换成等价的内部中 间表示——属性字序列。词法分析时发现的 词法错误大多是单词拼写错误,这或者是因 为书写错误,或者是因为输入错误,假定不 会有连续几个字符的错误,从而可以假定有 如下几类词法错误: 拼错一个字符,如RECORD错写成RCCORD。 遗漏一个字符,如REPEAT错写成REPET。 多拼一个字符,如UNTIL错写成UNTILE。 相邻两个字符颠倒了次序,如LABEL错写 成LABLE。
12.1.3 错误复原
由于错误的存在,往往使编译程序不能正常地继续 下去,早期的一些编译程序,例如,ALGOL 60语言 的编译程序采用结束编译的办法。如今,几乎所有 常用程序设计语言的编译程序都能在发现源程序中 的错误时继续进行编译,以便一次编译能查出尽可 能多的错误。 在编译的过程中,发现源程序的错误时采取一定的 措施,使得能继续编译下去,这称为错误复原。如 果把所给不正确程序变换成正确的程序,则称之为 错误校正。显然,如前所述的原因,错误校正是极 其困难的。
12.1.3 错误复原
词法分析时,如果发现输入字符串存在一个错误, 这表明,该输入字符串不是相应文法的句子,是否 就此不再继续词法分析呢?如果语法分析时,类似 地发现中间表示符号串中存在错误,表明不是相应 文法的句子,是否也不再继续语法分析呢?对于一 个实用的编译程序来说,它不应只能处理正确的程 序,它还必须能处理源程序中出现的错误,使得编 译工作能继续正常进行下去,不是发现一个错误就 结束编译,而是继续下去,以便查出全部错误。
12.1.2 错误的种类
④ 违反环境限制的错误。一个程序设计语 言可以有丰富的表达能力,用以书写各种应 用领域的程序,然而由于编译程序的实现问 题,一个手头上可用的编译程序往往对它所 能接受的源程序加某些限制。例如,Pascal 语言中过程的可调数组参数就不是每个编译 程序都可以接受的。另外,如标识符的长度 、整数的最大值范围、IF语句的最大嵌套层 数和数组的最大维数等,都可能会有一定的 限制。
由于程序设计语言的语法用上下文无关文法描述, 源程序可由基于某种分析技术的识别程序精确地识 别,源程序中的语法错误总可自动地查出。
12.3.1 语法错误的复原
不言而喻,不同的分析技术发现错误的手段和方式 是不同的。例如,LL(1)与LR(1)分析技术都是当前 栈顶状态与当前输入符号配对所对应的分析表元素 空白时为出错。然而,对于优先技术,则是当前栈 顶符号和当前输入符号匹配时,它们之间不存在优 先关系而发现错误。显然,有的分析技术可对所发 现的错误准确地定位,采取一定的措施,使语法分 析能继续进行下去。