目录
一、编译程序的基本过程
-
词法分析
- 输入:字符流
- 输出:记号流(如标识符、关键字)
- 任务:识别单词符号,检查非法字符(如
@
)。 - 错误示例:括号不配对属于语法分析阶段。
-
语法分析
- 输入:记号流
- 任务:组合单词为语法结构(如表达式、语句),检查结构合法性。
- 示例:C/C++语句合法性分析。
-
语义分析
- 任务:类型检查、上下文审查(如变量未声明、除数不为零)。
- 错误类型:
- 静态语义错误(编译时发现,如类型不匹配)。
- 动态语义错误(运行时发现,如数组越界)。
-
中间代码生成
- 生成关系:中间代码是根据语义分析产生的,需经过优化链接后最终生成可执行的目标代码。
- 引入目的:进行与机器无关的代码优化处理。
- 常见形式:后缀式(逆波兰式)、三元式(三地址)、四元式和树等形式。
- 需考虑的问题:
- 如何生成较短的目标代码。
- 如何充分利用计算机中的寄存器,减少目标代码访问存储单元的次数。
- 如何充分利用计算机指令系统的特点,以提高目标代码的质量。
- 前缀表达式:例如“+ab”,运算符在操作数之前。
- 中缀表达式:例如“a+b”,运算符在两个操作数中间,这是一般正常的表达式形式。
- 后缀表达式:例如“ab+”,运算符在操作数之后。三种表达式其实就是树的三种遍历,前缀、中缀、后缀表达式分别对应树的前序、中序、后序遍历 。
- 后缀表达式求法:从左到右开始,先把表达式加上括号,再依次把运算符加到本层次的括号后面。
-
代码优化
- 目标:减少寄存器访问次数,提高指令效率。
-
目标代码生成
- 输出:可执行的机器代码。
真题示例:
将编译器的工作过程划分为词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成时,语法分析阶段的输入是( ),若程序中的括号不配对,则会在( )阶段检查出错误。
A、记号流 B、字符流 C、语义分析 D、目标代码生成
- 解析:词法分析将源程序的字符流转换为记号流,语法分析的输入是词法分析的输出即记号流;括号不配对属于程序结构上的错误,是在语法分析阶段检查出来的,语义分析主要检查类型等语义相关问题,目标代码生成是最后生成可执行代码阶段。
以编译方式翻译C/C++源程序的过程中,( )阶段的主要任务是对各条语句的结构进行合法性分析。
A.词法分析 B.语义分析 C.语法分析 D.目标代码生成
- 解析:语法分析的主要任务是分析各条语句的结构是否合法,词法分析主要是识别单词,语义分析侧重于类型检查等语义层面,目标代码生成是生成最终的可执行代码。
表达式 (a - b) * (c + d) 的后缀式(逆波兰式)是( )
A、abcd-+* B、ab-c+d* C、abc-d-/* D、ab-cd+*
- 解析:按照后缀表达式求法,先给表达式加上括号为“((a - b) * (c + d))” ,然后依次把运算符加到本层次括号后面,得到“ab-cd+*” 。
二、文法(Chomsky分类)(编译相关)
1. 字母表与字符
字母表(Σ)是字符的非空有穷集合,字符是字母表Σ中的元素。例如,Σ = {a, b},a或b就是字符。
2. 字符串
由Σ中的字符组成的有穷序列。如a,ab,aaa都是Σ上的字符串。
字符串的长度:指字符串中的字符个数,如|aba| = 3。
空串(ε):由零个字符组成的序列,|ε| = 0。
3. 字符串的连接
字符串S和T的连接是指将串T接续在串S之后,表示为S·T,连接符号“·”可省略。对于字母表Σ的任意字符串S,S·ε = ε·S = S。
Σ*:指包括空串ε在内的Σ上所有字符串的集合。例如,若Σ = {a, b},Σ* = {ε, a, b, aa, bb, ab, ba, aaa, …} 。
4. 字符串的方幂
把字符串α自身连接n次得到的串,称为字符串α的n次方幂,记为αⁿ 。α₀ = ε,αⁿ = ααⁿ⁻¹ = αⁿ⁻¹α(n > 0)。
5. 字符串集合的运算
或(合并):设A,B代表字母表Σ上的两个字符串集合,A∪B = {α|α∈A或α∈B}。
积(连接):AB = {αβ|α∈A且β∈B}。
幂:Aⁿ = AA…A(n个A,n ≥ 0),并规定A⁰ = {ε}。
正则闭包:A* = A⁰∪A¹∪A²∪…,即A上所有字符串的集合(包括空串)。
正闭包:A⁺ = A¹∪A²∪…,即A上所有非空字符串的集合 。
-
定义:文法 G=(V,T,P,S)
- V:非终结符(如
E
,T
) - T:终结符(如
+
,0-9
) - P:产生式规则(如
E → E+T
) - S:起始符号(如
E
)。
- V:非终结符(如
-
分类:
类型 名称 特点 应用 0型 短语文法 无限制,等价于图灵机 通用计算 1型 上下文有关文法 非终结符替换依赖上下文 自然语言处理 2型 上下文无关文法 非终结符替换独立于上下文 程序设计语言语法 3型 正规文法(正则文法) 等价于正规式,用于词法分析 词法规则(如标识符)
三、正规式与正规集
- 基本单位:语言中具有独立含义的最小语法单位是符号(单词),如标识符、无符号常数与界限符等。词法分析的任务是把构成源程序的字符串转换成单词符号序列。
- 描述规则:词法规则可用3型文法(正规文法)或正规表达式描述,它产生的集合是语言规定的基本字符集Σ(字母表)上的字符串的一个子集,称为正规集。
- 运算符优先级:闭包(
*
) > 连接(·
) > 或(|
)。 - 示例:以Σ = {a, b}为例,列举一些正规式和相应的正规集:
- 正规式ab,对应正规集为字符串ab构成的集合。
- 正规式a|b,对应正规集为字符串a、b构成的集合。
- 正规式a∗,对应正规集为由0个或多个a构成的字符串集合。
- 正规式(a∣b)∗,对应正规集为所有字符a和b构成的串的集合。
- 正规式a(a∣b)∗,对应正规集为以a为首字符的a、b字符串的集合。
- 正规式(a∣b)∗abb,对应正规集为以abb结尾的a、b字符串的集合。
真题示例:
在仅由字符a、b构成的所有字符串中,其中以b结尾的字符串集合可用正规式表示为()
A.(b|ab)b B.(ab)b C.ab*b D.(a|b)*b
-
选项 A:
(b|ab)*b
(b|ab)*
可以生成任意由b
或ab
组成的序列(如b
,ab
,bab
,abab
, ...)。- 最后接一个
b
,确保以b
结尾。 - 问题:
(b|ab)*b
可以生成abb
(合法),但无法生成aab
(因为a
必须后跟b
)。
-
选项 B:
(ab*)*b
ab*
表示a
后跟任意数量b
(如a
,ab
,abb
, ...)。(ab*)*
可以生成ε
,a
,ab
,aab
,abab
, ...。- 最后接
b
,确保以b
结尾。 - 问题:无法生成
bb
(因为a
必须至少出现一次)。
-
选项 C:
a*b*b
a*
表示任意数量a
,b*
表示任意数量b
。a*b*b
可以生成ab
,aab
,abb
,aabb
, ...。- 问题:无法生成
b
(因为a*
和b*
至少有一个a
或b
)。
-
选项 D:
(a|b)*b
(a|b)*
表示任意由a
和b
组成的字符串(包括空串)。- 最后接
b
,确保以b
结尾。
由字符a、b构成的字符串中,若每个a后至少跟一个b,则该字符串集合可用正规式表示为( )。
A. (b|ab) * B. (ab* ) * C. (ab ) * D. (a|b) *
-
选项 A:
(b|ab)*
b
表示单独的b
,ab
表示a
后跟b
。(b|ab)*
可以生成b
,ab
,bb
,abb
,bab
,abab
, ...。
-
选项 B:
(ab*)*
ab*
表示a
后跟任意数量b
(包括a
后不跟b
,即a
)。(ab*)*
可以生成a
,aa
,ab
,aab
, ...。- 问题:允许
a
单独出现(如a
或aa
),违反规则。
-
选项 C:
(a*b*)*
a*
和b*
允许任意数量的a
和b
,包括a
单独出现。- 可以生成
a
,aa
,ab
,ba
,aab
, ...。 - 问题:允许
a
单独出现或a
后不跟b
(如aa
)。
-
选项 D:
(a|b)*
- 表示所有由
a
和b
组成的字符串。 - 问题:允许
a
单独出现或a
后不跟b
(如a
,aa
)。
- 表示所有由
简单算术表达式的结构可以用下面的上下文无关文法进行描述(E为开始符号),()是符合该文法的句子。
文法规则:
E → T | E + T T → F | T * F F → -F | N N → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
选项:
A.2--3*4
B.2+-3*4
C.(2+3)*4
D.2*4-3
- 文法规则:以E为开始符号,定义了简单算术表达式的结构。具体规则为:
- E可推导为T或者E+T;
- T可推导为F或者T*F;
- F可推导为 -F或者N;
- N可推导为0 - 9中的任意一个数字。
E -> E + T * -F 对应选项B (乘法的 -3 和 4可以对调,所以符合)。
四、有限自动机(FA)
-
DFA(确定的FA)
- 五元组:(S,Σ,f,s0,Z)
- f:单值转换函数(唯一后继状态)。
- 特点:输入字符对应唯一状态转移。
- 五元组:(S,Σ,f,s0,Z)
-
NFA(不确定的FA)
- 特点:
- 同一输入可能转移到多个状态。
- 允许
ε
转移。
- 等价转换:通过子集构造法转换为DFA。
- 特点:
真题示例:
第一题:C,存在1使状态改变和循环
第二题:A,0110可以满足(其他选项首尾已经不满足)
五、语法分析方法
方法 | 方向 | 核心思想 | 示例 |
---|---|---|---|
自上而下 | 最左推导 | 从开始符号推导输入串 | 递归下降法 |
自下而上 | 最右归约 | 从输入串归约到开始符号 | 移进-归约(栈实现) |