编译原理 (一)

来源:互联网 发布:哈萨克软件下载 编辑:程序博客网 时间:2024/05/21 06:57

什么是编译器?

编译器是一种程序
核心功能是把源代码翻译成目标代码
解释器和编译器的区别:

解释器是一条一条的解释执行源语言。比如php,postscritp,javascript就是典型的解释性语言。  
编译器是把源代码整个编译成目标代码,执行时不在需要编译器,直接在支持目标代码的平台上运行,这样执行效率比解释执行快很多。比如C语言代码被编译成二进制代码(exe程序),在windows平台上执行。
读入源语言后,解释器和编译器都要进行词法分析、语法分析和语义分析,之后,二者开始有所分别。解释器在语义分析后选择了直接执行语句;编译器在语义分析后选择将将语义存储成某一种中间语言,之后通过不同的后端翻译成不同的机器语言(可执行程序)。

编译器结构

这里写图片描述
编译器由多个阶段组成,每个阶段处理不同的问题

程序语言的语法描述

这里写图片描述
这里写图片描述

文法

描述语言的语法结构的形式规则

以英语来进行类比:
这里写图片描述
这里写图片描述
文法定义:
文法G 定义为四元组(VT ,VN,P,S)
VN :非终结符集合(非空)
VT :终结符集合(非空), 且VT,VN相交为空集
S :文法的开始符号(识别符号), S属于VN
P :产生式集合(规则集合),有限
开始符S至少必须在某个产生式的左部出现一次

例如:
定义只含+,*的算术表达式的文法
G=<{i,+,*,(,)}, {E},E,P>,其中P由下列产生式组成;
E —>i
E —>E+E
E —>E*E
E —>(E)

巴科斯范式(BNF)
“—>”也可以用“::=”表示,这种表示叫做巴科斯范式
因为“—>”无法用ASCII表示

几点约定:
1. P—>α1 , P—>α2 ,P—>α3 ……P—>αn
可缩写为P —> α1| α2|……| αn
| 表示“或”
2. 表示一个文法时,通常只要给出开始符号和产生式
3. 大写字母开头为非终结符,小写字母开头为终结符

这里写图片描述
句型:是由终结符和非终结符组成
句子:只含终结符

给出文法推语言
例子1:
(i*i+i)是文法G(E): E—> i | E+E |E*E|(E) 的一个句子
证明:
E =>(E)
  =>(E+E)
  =>(E*E+E)
  =>(i*E+E)
  =>(i*i+E)
  =>(i*i+i)

例子2:
文法G1(A):A —> c | Ab,G1(A)的语言
A=>c
A=>Ab
  =>cb
A=>Ab
  =>Abb
  =>Abbbb
  =>Abb….bb
  =>cbb….bb

给出语言推文法
例子:
给出产生语言为{a^mb^n|1<=n<=m<=2n}的文法
G(S):
S —> ab | aab
S —> aSb | aaSb
先从最简单的往上分析

语法树

用一张图表示一个句型的推导,称为语法树
这里写图片描述

语法树与二义性

如果一个文法存在某个句子对应两颗不同的语法树,则说这个文法是二义的。
如:
这里写图片描述
语言的二义性:一个语言是二义的,如果对它不存在无二义性的文法
可能存在G和G’,一个为二义的,一个为无二义的。但L(G)=L(G’)
二义性问题是不可判定问题,即不存在一个算法,它能在有限步骤内,确切的判定一个文法是否是二义的
可以找到一组无二义文法的充分必要条件

二义文法:G(E): E—> i | E+E |E*E|(E)(一个句子有两颗树)
无二义文法:
G(E): E—> T | E+T
T —> F | T*F
F —> (E) | i

表达式 — > 项|表达式+项
项 —> 因子|项*因子
因子 —> (表达式)| i
改进后,它画出的语法树是唯一的
这里写图片描述

文法的四种类型:

1. 0型文法(短语文法)
产生式的形式:α→β
α∈(VN∪VT)* ,且至少含一个非终结符 ,β∈(VN∪VT)*
对产生式没有任何限制
例如:A0→A0 , A1→B

2. 1型文法(上下文有关文法):
  产生式形如:α→β
  其中, |α|<=|β|, 仅仅 S→ε除外
  产生式的形式描述:xUy —> xuy
  (其中,x、y、u∈(VN∪VT)*,β≠ε,A∈VN)
  有U出现时,必须关注是否有x,y。有x,y时才能将U用u代替
  例如:0A0→011000 1A1→101011

3. 2型文法(上下文无关文法):
对任一产生式α→β,都有α∈VN,β∈(VN∪VT)*
  产生式的形式描述:A→β (A∈VN)
  即β取代A时,与A所处的上下文无关。

  例如:G[S]:S→01 S→0S1

4. 3型文法(正规文法)
  每个产生式均为 “A→aB”或“A→a” —— 右线性
   “A→Ba”或“A→a” —— 左线性
  其中,A、B∈VN,a∈VT*
  产生的语言称“正规语言”
  例如:G[S]: S→0A | 0
  A→1B | B
  B→1 | 0

左边式子都是非终结符最有可能是2型,3型文法
这里写图片描述

对于现今程序设计语言,在编译程序中,仍然采用上下文无关文法来描述其语言结构

一. 词法分析

词法分析的任务:
从左至右逐个字符地对源程序进行扫描,产生一个个单词符号

对于词法分析器的要求:
功能:
输入源程序,输出单词符号
单词符号的种类:
1. 基本字:begin,repeat…
2. 标识符:表示各种名字:如变量名,数组名和过程名
3. 常数:各种类型的常数
4. 运算符:+,-,*,/
5. 界符:逗号,分号,括号和空白

输出单词符号的表现形式:
一个二元组(单词种别,单词自身的值)
单词种别通常用整数编码表示:
若一个种别只有一个单词符号,则种别的编码就代表该单词符号,假定基本字,运算符和界符都是一符一种
若一个种别符有多个单词符号,则对于每个单词符号,给出种别编码和自身的值
标识符单列一种,标识符自身的值表示成按机器字节划分的内部码
常数按类型分钟,常数的值表示成标准的二进制方式

例子:
FORTRAN程序

IF (5.EQ.M) GOTO 100

输出单词符号
逻辑 IF (34,-)
左括号 (2,-)
整常数 (20,‘5’的二进制)
等号(.EQ.) (6,-)
标识符 (26,‘M’)
右括号 (16,-)
GOTO (30,-)
标号 (19,‘100’的二进制)

C程序

while(i>=j)  i--;

输出单词符号(二元组)
<while , ->
<( , ->
<id , 指向i的符号表项的指针>
<>= , ->
<id , 指向j的符号表项的指针>
<) , ->
<id , 指向i的符号表项的指针>
<– , ->
< ; , ->

词法分析器在编辑器中的地位:
这里写图片描述

词法分析器的结构
这里写图片描述-

状态转换图

状态转换图是一张有限方向图
结点代表状态,用圆圈表示
状态之间用弧线连接,箭弧上的标记(字符)代表射出结状态下可能出现的输入字符或字符类
一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态

状态转换图可用于识别一定的字符串
若存在一条从初态到某一终态的道路,且这条路上所有弧上的标记符连接成的字等于a,则称a为改状态图所识别(接受)
这里写图片描述

小例子:
假如下图是一个程序语言的全部语法规则
这里写图片描述

它的状态转换图可画为:

这里写图片描述

状态转换图的实现:
思想:每个状态结点对应一小段程序
具体方法:
1. 对不含回路的分叉结点,可用一个CASE语句或一组IF -THEN-ELSE语句实现
这里写图片描述

  1. 对含回路的状态结点,可对应一段由WHILE结构和IF语句构成的程序
    这里写图片描述

  2. 终态结点表示识别出某种单词符号,对应语句
    RETURN (C , VAL)
    C为单词种别 VAL为单词自身值

全局变量与过程
1. ch字符变量,存放最新读入的源程序字符
2. strToken 字符数组,存放构成单词符号的字符串
3. GetChar 子程序过程,把下一个字符读入到ch中
4. GetBC 子程序过程,跳过空白符,直至ch中读入一非空白符
5. Concat 子程序,把ch中的字符连接到strToken
6. IsLetter和IsDisgital布尔函数,判断ch中字符是否为字母和数字
7. Reserve整型函数,对于strToken中的字符串查找保留字表,若他是保留字则给出它的编码,否则回送0
8. Retract子程序,把搜索指针回调一个字符位置
9. InsertId 整型函数,将strToken中的标识符插入符号表,返回符号表指针
10. InsertConst 整型函数过程,将strToken中的常数插入常数表,返回常数表指针

正规表达式与有限自动机(DFA)

这里写图片描述
这里写图片描述

正规集和正规表达式:
正规集可以用正规表达式表示
正规表达式是表示正规集的一种方法
一个字集合是正规集当且仅当它能用正规式表示

正规式和正规集的递归定义

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

确定有限自动机

这里写图片描述

这里写图片描述

DFA可以表示为状态转换图:
假定DFA M含有m个状态和n个输入字符
这个图含有m个状态结点,每个结点顶多含有n条箭弧射出,且每条箭弧用不同的输入字符来表示

这里写图片描述
DFA M所识别的字的全体记为L(M)

这里写图片描述
选A 从初态出发可以到达终态的这条通路上所有的字符构成了一个字,而
A直接到终态,中间无字符就是空字
而B代表Φ

非确定有限自动机(NFA)

这里写图片描述

hh

这里写图片描述

这里写图片描述

将 DFA转换为NFA


这里写图片描述

这里写图片描述

小例子:运用以上三条规则
这里写图片描述
弧上的标记不允许有ε,要消除ε
这里写图片描述

最后一步:
这里写图片描述
从一个状态出发,识别若干个ε后能到达的状态,都在这个集合里
这里写图片描述

这里写图片描述

这里写图片描述
对1做ε的闭包,得到{1,2},而J为I中的某个状态出发进过a弧而到达的状态的集合
1 —> 5,4
2 —> 3
{1,2}识别a后到达的状态集{3,4,5}
再对{5,4,3}做ε的闭包,得到{5,4,3,6,2,7,8}
这里写图片描述
第一行第一列就是X的ε闭包
这个表转换为状态集之间的转换关系
例如:
这里写图片描述
第一行:X的闭包{X,5,1},输入a状态转换到{5,3},再对{5,3}做新的闭包得{5,3,1},Ib同理得{5,4,1},{5,3,1}和{5,4,1}在列中未出现,因此加入到列中。以此类推
这里写图片描述
初态就是包含X的集合{X,5,1}
终态就是包含Y的集合
将每个集合看做一个状态,给一个新的编号
这里写图片描述

原创粉丝点击