第一讲 引论
1.1 什么是编译程序
课程内容是:介绍程序设计语言编译程序构造的基本原理和基本实现技术。
-
翻译程序(Translator)
-
把某一种语言程序(源语言程序)等价地转换未另一种语言程序(目标语言程序)的程序。
-
-
编译程序(Compiler)
-
把某一种高级语言等价地转换为另一种低级语言程序(汇编语言或机器语言)的程序。
-
诊断编译程序( Diagnostic Compiler)
-
优化编译程序( Optimizing Compiler)
-
交叉编译程序( Cross compiler)
-
可变目标编译程序( Retargetable Compiler)
-
-
解释程序
-
把源语言写的源程序作为输入,但不产生目标程序,而是边解释边执行源程序。
-
1.2 学习目的
- 理解计算系统
- 设计计算系统
- 训练计算思维( Computational Thinking)
- 包括一系列广泛的计算机科学的思维方法
- 抽象
- 自动化
- 问题分解
- 递归✨
- 权衡
- 保护、冗余、容错、纠错和恢复
- 利用启发式推理来寻求解答
- 在不确定情况下的规划、学习和调度
- 包括一系列广泛的计算机科学的思维方法
1.3 编译过程
编译程序工作的五个阶段
1.3.1 词法分析
-
任务:输入源程序,对构成源程序的字符串进行扫描和分解,识别出单词符号。
-
依循的原则:构词规则
-
描述工具:有限自动机
1.3.2 语法分析
-
任务:在词法分析的基础上,根据语法规则把单词符号,分解成各类语法单位(语法范畴)
-
原则:语法规则
-
描述工具:上下文无关文法
1.3.3 中间代码产生
-
任务:对各类语法单位按语言的语义进行初步翻译。
-
原则:语义规则
-
描述工具:属性文法
-
中间代码:三元式、四元式,树……
-
Z:=X+0.618*Y 翻译称四元式:
序号 OPR OPN1 OPN2 RESULT 注释 (1) * 0.618 Y T1 T1:=0.618*Y (2) + X T1 T2 T2:=X+T1 (3) := T2 Z Z:=T2
1.3.4 优化
- 任务:对前阶段产生的中间代码进行加工变换,期待在最后阶段产生更高效的目标代码。
- 原则:程序的等价变换原则
1.3.5 目标代码产生
- 任务:把中间代码变换成特定机器上的目标代码
- 依赖于硬件系统结构和机器指令的含义
- 目标代码的三种形式
- 汇编指令代码:需要进行汇编
- 绝对指令代码:可直接运行
- 可重新定位指令代码:需要链接
1.4 编译程序的结构
编译程序总框
1.4.1 出错处理
- 出错处理程序:发现源程序中的错误,并把错误报告给用户
- 语法错误
- 与源程序中不符合语法规则的错误
- 非法字符、括号不匹配、缺少 ; , 等……
- 语义错误
- 源程序中不符合语义规则的错误
- 说明错误、作用域错误、类型不一致……
1.4.2 遍(pass)
- “遍”,就是对源程序或者源程序的中间表示从头到尾扫描一遍
- 阶段与遍是不同的概念
- 一遍可以由若干个阶段组成
- 一个阶段也可以由若干遍完成
1.4.3 编译的前端和后端
- 编译前端
- 与源语言有关,如词法分析,语法分析,语义分析与中间代码产生,与机器无关的优化
- 编译后端
- 与目标机有关,与目标机有关的优化,目标代码产生
- 带来的好处
- 程序逻辑结构清晰
- 优化更充分,有利于移植
1.5 编译程序的生成
-
以机器语言和汇编语言为工具
- 优点:可以针对具体的机器,充分发挥计算机的系统功能,生成的程序效率高。
- 缺点:程序难读、难写、易出错、难维护、生产效率低……
-
高级语言书写
- 利用已有的某种语言的编译程序实现对另一语言的编译程序。
- 程序易读、易理解、容易维护、生产的效率高。
-
移植方法
- 把一种机器上的编译程序移植到另一种机器上。
-
自编译方法
-
编译程序自动产生
-
编译程序-编译程序,编译程序产生器,编译程序书写系统
-
LEX:词法分析程序产生器
-
YACC:语法分析程序产生器
-
第二讲 高级程序设计语言概述
2.1 常用的高级程序设计语言
- 高级语言
- FORTRAN:数值计算
- COBOL:事务处理
- PASCAL :结构化程序设计
- LISP:函数式程序设计
- PROLOG:逻辑程序设计
- C:系统程序设计
- Smalltalk:面向对象程序设计
- Java:Internet应用,可移植性
- Python:解释型,动态编程
- 高级程序设计语言的优点
- 相对机器语言或汇编语言,高级程序设计语言
- 更接近于数学语言和工程语言,更直观、自然和易于理解
- 更容易验证其正确性、改错
- 编写程序的效率更高
- 更容易移植
- 相对机器语言或汇编语言,高级程序设计语言
2.2 程序设计语言的定义
-
标识符是语法概念,名字是语义概念
-
程序语言的定义
- 语法
- 语义
- 语用*
2.2.1 语法
-
程序本质上是一定字符集上的字符串
-
语法:一组规则,用它可以形成和产生一个合式(well-formed)的程序
-
词法规则:单词符号的形成规则
- 单词符号是语言中具有独立意义的最基本结构
- 一般包括:常数、标识符、基本字、算符、界符等
- 描述工具:有限自动机
-
语法规则:语法单位的形成规则
- 语法单位通常包括:表达式、语句、分程序、过程、函数、程序等
- 描述工具:上下文无关文法
-
语法分析实例
式子 解析 表示含义 E–>i i代表标识符,E代表一个算术表达式 一个算术表达式可以由一个标识符表示 E–>E+E 右边的两个E表示子表达式 一个算术表达式可以由两个子表达式通过+连接起来,表示 E–>E*E *就是一个符号,不表示乘法 一个算术表达式可以由两个子表达式通过*连接起来,表示 E–>(E) 一个算术表达式在外面加上括号,还是一个算术表达式 -
语法规则和词法规则定义了程序的形式结构
-
定义语法单位的意义属于语义问题
2.2.2 语义
- 一组规则,用它可以定义一个程序的意义
- 描述方法:
- 自然语言描述
- 二义性、隐藏错误和不完整性
- 形式描述
- 操作语义
- 指称语义
- 代数语义
- 自然语言描述
2.2.3 程序语言的基本功能
-
程序,本质上是描述一定数据的处理过程
-
基本功能
- 描述数据和对数据的运算
-
程序的层次结构
2.2.4 程序语言成分的逻辑意义和实现意义
- 抽象的逻辑的意义
- 数学意义
- 计算机实现的意义
- 具体实现
- 计算思维与数学思维的不同
2.3 高级程序设计语言的一般特性
2.3.1 高级语言的分类
-
强制式语言 (Imperative Languge)/ 过程式语言
- 命令驱动,面向语句
- FORTRAN、C、Pascal,Ada
-
应用式语言 (Applicative Language)
- 注重程序所表示的功能,而不是一个语句接一个语句地执行,函数式语言。
- LISP、ML(meta language
- 基于规则的语言( Rule-based Language)
- 检查一定的条件,当它满足值,则执行适当的动作
- Prolog
-
基于规则的语言(Rue- based Language)
-
面向对象语言(Object-Oriented Language)
- 封装性 、继承、多态
2.3.2 程序结构
-
FORTRAN
- 一个程序由一个主程序段和若干辅程序段组成
- 辅程序段可以是子程序、函数段或数据块
- 每个程序段由一系列的说明语包和执行语句组成,各段可以独立编译
- 模块结构,没有嵌套和递归
- 各程序段中的名字相互独立立的程序段中代表不同的名字。
-
PASCAL
-
PASCAL程序本身可以看成是一个操作系统调用的过程,过程可以嵌套和递归。
-
一个 PASCAL过程
过程头 说明段(由一系列的说明语句组成) begin 执行体(由一系列的执行语句组成) end
-
作用域
-
同一标识符在不同过程中代表不同的名字
-
一个名字能被使用的区域范围叫做作用域。
-
规则:最近嵌套原则
-
一个在子程序B1中说明的名字X只在B1中有效(局部于B1)
-
如果B2是B1的一个内层子程序且B2中对标识符X没有新的说明,则原来的名字X在B2中仍然有效
-
如果B2对Ⅹ重新作了说明,那么,B2对X的任何引用都是指重新说明过的这个Ⅹ。
-
✨💖类似于Java中,继承关系,子类对属性的调用,用就近原则。重新说明类似于方法重写或者属性重新定义。
program main var A, B: real; ... procedure P1 var B:boolean; ... begin ... end procedure P2 var A:integer; ... begin ... end begin ... end
- 在上述代码中,main体中的A和B分别在子程序P1和子程序P2中被重新定义。它的作用域随之发生改变。
-
-
-
-
Java
- 面向对象语言的代表
- 类(class)
- 继承
- 面向对象语言的代表
2.3.3 数据结构与操作
-
三要素:属性、值、操作。
-
初等数据类型
-
数值类型
- 整型、实形、复数、双精度
-
运算:+,-,*,/;
-
逻辑类型
- true、false
- 布尔运算:∨,∧,┑等
-
字符类型:符号处理
-
指针类型
-
-
标识符与名字
-
标识符
- 以字母开头的,由字母数字组成的字符串
- 标识符与名字两者有本质区别
- 标识符是语法概念
-
名字有确切的意义和属性
- 值:单元中的内容
- 属性:类型和作用域
-
数组
- 逻辑上,数组是由同一类型数据组成的某种n维矩形结构,沿着每一维的距离,称为下标。
- 数组可变与不可变
- 编译时能否确定其存贮空间的大小
- 访问
- 给出数组名和下标值,如A[10,i+j]
- 存放方式
- 按行存放(C,PASCAL),按列存放(FORTRAN)
-
字符串、表格、栈
- 字符串:符号处理、公式处理。
- 表格:本质上是一种记录结构
- 线性表:一组顺序化的记录结构
- 栈:一种特殊的线性表,先进后出,
POP
,PUSH
-
抽象数据类型( Abstract Data Type)
- A set of data values and associated, operations that are precisely specified, independent of any, particular, implementation.
- 抽象数据类型由数据集合、及其相关的操作组成,这些操作有明确的定义,而且定义不依赖于具体的实现。
- 一个抽象数据类型包括
- 数据对象集合
- 作用于这些数据对象的抽象运算的集合
- 这种类型对象的封装,即:除了使用类型中所定义的运算外,用户不能对这些对象进行操作
2.3.4 语句与控制结构
👌程序 = 数据结构 + 算法
- 表达式
- 表达式由运算量和算符组成
- 运算量:也称操作数,即数据引用或函数调用
- 算符:运算符,操作符
- 形式:
- 中缀、前缀、后缀
X*Y、 -A、 P↑或者p→
- 中缀、前缀、后缀
- 表达式形成规则
- 变量(包括下标变量)、常数是表达式。
- 若E1、E2为表达式,θ是一个二元算符,则E1E2是表达式。
- 若E是表达式,θ为一元算符,则θE(或Eθ)是表达式
- 若E是表达式,则(E)是表达式。
- 表达式由运算量和算符组成
- 算符的优先次序
- 一般的规定
- PASCAL:左结合A+B+C=(A+B)+C
- FORTRAN:对于满足左、右结合的算符可任取种,如A+B+C就可以处理成(A+B)+C,也可以处
理成A+(B+C)
- 代数性质
- 代数性质能引用到什么程度视具体的语言而定
- 在数学上成立的代数性质在计算机上未必完全成立
- A+b=b+A,在编程中不一定成立,比如A和B都是函数调用。
- 一般的规定
- 语句
- 赋值语句
- A:=B, 把A的值送到B所在的存储单元中。
- 名字的左值:该名字代表的存储单元的地址
- 名字的右值:该名字代表的存储单元的内容
- 控制语句
- 条件语句
- 循环语句
- 过程调用语句……
- 返回语句
- 赋值语句
- 语句的分类
- 功能
- 执行语句:描述程序的动作
- 说明语句:定义各种不同数据类型的变量或运算,定义名字的性质
- 形式
- 简单句:不包含其他语句成分的基本语句
- 复合句
- 功能
第三讲 高级程序设计语言的描述
3.1 上下文无关文法
- 文法:描述语言的语法结构的形式规则
3.1.1 描述文法的几个概念
-
字母表(alphabet)
任何语言的字母表指出了该语言中允许出现的一切符号
- 字母表:非空有穷字符集合,表示:∑
- 【例如】 ∑ = {a,b,c}
- ∑是字母表,由a,b,c 三个元素组成。
- 【例如】 ∑ = {a,b,c}
- 字母表中至少包含一个元素。
- 不包含任何字符的序列叫做空字,记为:ε
- ∑*表示里面的全体字,包括ε
- 字母表中的元素,可以是字母、数字或其他符号。
- 【例如】 ∑` = {0,1}
- ∑`是字母表,由0,1两个元素组成。
- 【例如】 ∑` = {0,1}
- 不同的语言有不同的字母表
- 英文的字母表是26个字母、数字和标点符号的集合;
- C 语言的字母表是字母、数字和若干专用符号组成。
- 字母表:非空有穷字符集合,表示:∑
-
字符(symbol)
- 字母表中的元素称为符号或字符
- 【例如】 ∑ = {a,b,c}
- a,b,c 是字母表 ∑ 中的符号。
- 【例如】 ∑’ = {0,1}
- 0,1 是字母表 ∑’ 中的符号。
- 【例如】 ∑ = {a,b,c}
- 字母表中的元素称为符号或字符
-
符号串(字)string
-
符号的有穷序列称为字符串
- 【例如】设有字母表 ∑ = {a,b,c},
- 则有符号串 a,b,ab,ba,cba,abc,…
- (a,b,ab,ba,cba,abc 等都是字母表∑上的符号串)
-
符号串总是建立在某个特定字母表上的且只能有字母表上的有穷多个符号组成.
-
符号串中符号的顺序是很重要的,
-
如ab和ba是字母表 ∑上的两个不同的符号串。
-
-
不包含任何符号的符号串,称为空符号串,用== ε \varepsilon ε== (epsilon)表示,即空符号串由 0 个符号组成,其长度 | ε \varepsilon ε | = 0。
-
-
连接(积)
U V = { α β ∣ α ∈ U & β ∈ V } UV=\{\alpha\beta|\alpha\in U\&\beta\in V\} UV={αβ∣α∈U&β∈V}
- 为U和V的连接;
- 设: U={a,aa}, V={b,bb}
- 那么:UV={ab, abb, aab, aabb}
- 因此:
- 对于任意一符号串X有:
- ε = X ε = X \varepsilon=X \varepsilon=X ε=Xε=X
- 所以对任意集合A,有
- { ε } = A { ε } = A \{\varepsilon\}=A\{\varepsilon\}=A {ε}=A{ε}=A
- 对于任意一符号串X有:
- 为U和V的连接;
-
空集 Φ 、 ε 、 { ε } \Phi、\varepsilon、\{\varepsilon\} Φ、ε、{ε}的区别
- Φ \Phi Φ表示不含任何元素的空集{ }
- 注意:
- ε \varepsilon ε是符号串,不是集合
- { ε } \{\varepsilon\} {ε} 表 示 由 空 符 号 串 表示由空符号串 表示由空符号串 ε \varepsilon ε 所 组 成 的 集 合 , 但 是 这 样 的 集 合 不 是 空 集 所组成的集合,但是这样的集合不是空集 所组成的集合,但是这样的集合不是空集 Φ \Phi Φ , 即 ,即 ,即 Φ \Phi Φ$不含空串。
-
V自身的 n次积记为: V n = V V . . . V ⏟ n个 V^n=\underbrace{V V...V}_{\text{n个}} Vn=n个 VV...V
- 规定 V 0 = { ε } V^0=\{\varepsilon\} V0={ε}
- 令 V ∗ = V 0 ∪ V 1 ∪ V 2 ∪ V 3 ∪ V^*=V^0 ∪ V^1∪ V^2∪ V^3∪ V∗=V0∪V1∪V2∪V3∪…称V*是V的闭包。
- 记 V + = V V ∗ V^+=V V^* V+=VV∗$ ,称$ V + V^+ V+是V的正则闭包
- 区别:如果U中没有ε,则U*中一定会包含ε,而U+中不会有ε。
-
设: U = { a , a a } U=\{a,aa\} U={a,aa}
-
那么:
- U ∗ = { ε , a , a a , a a a , a a a a , . . . } U^*=\{\varepsilon,a,aa,aaa,aaaa,...\} U∗={ε,a,aa,aaa,aaaa,...}
- U + = { a , a a , a a a , a a a a , . . . } U^+=\{a,aa,aaa,aaaa,...\} U+={a,aa,aaa,aaaa,...}
-
3.1.2 上下文无关文法
是这样一种文法,它所定义的语法范畴(或语法单位)是完全独立于这种范畴出现的环境。
-
一个上下文无关文法G是一个四元式
G = ( V T , V N , S , P ) G=(V_T,V_N,S,P) G=(VT,VN,S,P)
- VT:终结符集合(非空)
- VN:非终结符集合(非空),且 V T ⋂ V N = ∅ V_T \bigcap V_N=\varnothing VT⋂VN=∅。即一个符号不允许既是终结符又是非终结符。
- S:文法的开始符号, S ∈ V N S\in V_N S∈VN
- P:产生式集合(有限),每个产生式形式为
- P → α , P ∈ V N , α = ( V T ⋃ V N ) ∗ P\to\alpha, P\in V_N,\alpha =(V_T \bigcup V_N)^* P→α,P∈VN,α=(VT⋃VN)∗
- 开始符S至少必须在某个产生式的左部出现一次。
-
巴科斯范式(BNF)
- “→"由”::="表示
-
约定
-
其中:" | “表示” 或 ",称 α i \alpha_{i} αi为P的一个候选式
-
表示一个文法时,通常只给出开始符号和产生式
3.1.3 文法的形式定义的规则
- 规则也称产生式,是一个符号与一个符号串的有序对(A,
β
\beta
β),通常写作
- A → β A\to\beta A→β, (或: A : : = β A::=\beta A::=β)
- 其中A是规则左部,是一个符号,
- β \beta β 是规则左部,是一个符号串。
-
3.2 文法→语言
-
“→"表示定义,”=>"表示直接推出
-
定义:称αΑβ直接推出αΥβ,即
α A β = > α Υ β αΑβ=>αΥβ αAβ=>αΥβ
仅当A→Υ是一个产生式,且α、β∈( V T ∪ V N V_T∪V_N VT∪VN)*。
-
直接推出是把一个字符串中的一个非终结符的一次出现替换成它的候选式,而不是把一个字符串中的一个非终结符的多次出现进行替换。
-
结论
- 如果 α 1 → α 2 → … → α n α_1→α_2→…→α_n α1→α2→…→αn,则我们称这个序列是从 α 1 到 α n α_1到α_n α1到αn的一个推导。
- 若存在一个从 α 1 到 α n α_1到α_n α1到αn的推导,则称 a 1 a_1 a1可以推导出 α n α_n αn。
-
对文法G(E): E → i ∣ E + E ∣ E ∗ E ∣ ( E ) E→i|E+E|E*E|(E) E→i∣E+E∣E∗E∣(E).
问:如何从E=>(i+i).?
解答:由E->(E),所以E=>(E), 又E->E+E, 所以E=>(E+E), 又E->i, 所以E=>(i+E)=>(i+i)。
-
α 1 ⇒ ∗ α n α_1\xRightarrow{*}α_n α1∗αn 从α1出发,经过0步或若干步退出αn;
α 1 ⇒ + α n α_1\xRightarrow{+}α_n α1+αn 从α1出发,经过1步或若干步退出αn;
α ⇒ ∗ β α\xRightarrow{*}β α∗β, α =β或 α ⇒ + β α\xRightarrow{+}β α+β
-
句子、句型和语言
-
假定G是一个文法,S是它的终结符号,如果 S ⇒ ∗ α S\xRightarrow{*}α S∗α,则称α是一个句型
-
仅含终结符号的句型是一个句子。
-
文法G所产生的句子的全体是一个语言,记为L(G)。
L ( G ) = { α ∣ S ⇒ + α , α ∈ V T ∗ } L(G)=\{α|S\xRightarrow{+}α,α\in{V^*_T}\} L(G)={α∣S+α,α∈VT∗}
-
-
A→Ab,是一种递归定义,可以产生的句型有:Ab,Abb,Abbb,Abbb…b, 即它的语言就是这些所有句型的集合。
-
慕课上3.2 节有几个例题🎈
3.3 语法树与二叉性
3.3.1 最左推导和最右推导
-
从一个句型到另一个句型的推导往往不唯一
①E+E=>i+E=>i+i, 左边的E先被替换:最左推导
②E+E=>E+i=>i+i,右边的E先被替换:最右推导 -
最左推导:任何一步α=>β都是对α中最左非终结符进行替换;
-
最右推导:任何一步α→β都是对α中最右非终结符进行替换。
3.3.2 语法树
-
用一张图表示一个句型的推导,称为:语法树。
-
一棵语法树是不同推导过程的共性抽象
-
两点说明
-
在树中间,父子节点可以同名
-
语法树并不反映节点产生的先后次序,只反映了语法符号的定义(构成关系),
-
3.3.3 二义性
-
文法的二义性:如果一个文法存在某个句子对应两棵不同的语法树,则说这个文法是二义的
G(E):E→iE+EE*E(E)是二义文法 -
语言的二义性:一个语言是二义的,如果对它不存在无二义的文法,对于语言L,可能存在G和G`,使得L(G)=L(G′)=L,有可能其中一个文法为二义的,另一个为无二义的。
-
语言的二义性
- Jack saw Tom in a boat.
- 两种意思
- Jack看见Tom在一条船上
- Jack在船上,看见了Tom。
注意:根据已有知识,我们只能判断一个文法是二义的,但是不能确切地判定一个文法不是二义的。
3.3.4 形式语言
-
乔姆斯基于1956年建立形式语言体系,他把文法分成四种类型:0、1、2、3型
-
与上下文无关文法(2型)一样,它们都由四部分组成,但对产生式的限制有所不同。
G = ( V T , V N , S , P ) G=(V_T,V_N,S,P) G=(VT,VN,S,P)
- VT:终结符集合(非空)
- VN:非终结符集合(非空),且 V T ⋂ V N = ∅ V_T \bigcap V_N=\varnothing VT⋂VN=∅。即一个符号不允许既是终结符又是非终结符。
- S:文法的开始符号, S ∈ V N S\in V_N S∈VN
- P:产生式集合(有限)<四种文法类型的区别在于此>
-
0型(短语文法,图灵机)
- 产生式形如: a → b
- 其中: a ∈ ( V T ∪ V N ) ∗ a\in (V_T ∪ V_N)* a∈(VT∪VN)∗且至少含有一个非终结符; β ∈ ( V T ∪ V N ) ∗ β\in (V_T ∪ V_N)* β∈(VT∪VN)∗
-
1型(上下文有关文法,线性界限自动机)
- 产生式形如: a → b
- 其中:|a| ≤|b|,仅 S → ε 例外
-
2型(上下文无关文法,非确定下推自动机)
- 产生式形如: A → β
- 其中: A ∈ V N ; β ∈ ( V T ∪ V N ) ∗ A\in V_N;β\in (V_T ∪ V_N)* A∈VN;β∈(VT∪VN)∗
-
3型(正规文法,有限自动机)
- 右线性文法
- 产生式形如: A → αB 或 A → α
- 其中: α∈ VT*;A,B∈VN
- 左线性文法
- 产生式形如: A → B α 或 A → α
- 其中: α∈VT*;A,B ∈VN
- 右线性文法
-
四种文法描述能力比较
- 程序设计语言不是上下文无关语言,甚至不是上下文有关语言
- L7={αcα| a∈{a,b}*}不能由上下文无关文法产生,甚至连上下文有关文法也不能产生,只能由0型文法产生
- 标识符引用
- 过程调用过程中,“形-实参数的对应性"(如个数,顺序和类型一致性)
- 对于现今程序设计语言,在编译程序中,仍然采用上下文无关文法来描述其语言结构
第二讲和第三讲对应学校老师讲课的第二章。课件完全是一样的