【编译原理】01引论

1.1 翻译程序、编译程序、解释程序

        翻译程序:把某一种语言程序(称之为 源语言程序)等价地转换成另一种语言程序(称之为 目标语言程序) 的程序。

        编译程序:把某一种高级语言程序等价的转换称另一种低级语言程序(如汇编语言或及其语言程序) 的程序。编译程序可以分为诊断编译程序(重点放在对程序员写的程序进行挑错和诊断,帮助程序员快速完成对程序正确性的检查)、优化编译程序、交叉编译程序、可变目标编译程序。

        解释程序:把源语言写的 源程序 作为输入,但不产生目标程序,而是 边解释边执行 源程序本身。

        区分编译程序和解释程序:以将英文文档翻译为中文文档为例,编译就是直接将稿子翻译成中文,而解释就是一边说一边翻译成中文。

        翻译程序与解释程序的比较 :翻译程序:以源程序输入顺序处理程序语句 解释程序:按照源程序的逻辑流程进行工作。

        根据编译器的编译过程,编译程序可以分为编译器和解释器两种。 编译器是将源代码转换成可执行程序,然后再运行可执行程序; 解释器是在程序界面中输入一条命令后,将直接得到运行结果; 常用的开发工具,如VC、delphi等的是编译器。 Matlab、foxpro等是解释器。数据库的查询端也是解释器。

编译器
解释器

1.2 计算思维

        抽象:从众多的事物中抽取出共同的、本性的特征,舍弃其非本质的特征。

        自动化:编译原理中的自动化如有限自动机、预测分析程序等

        分解:将大规模的复杂问题分解成若干个较小规模的、更简单的问题加以解决。

        递归:问题的解决又依赖类似问题的解决,只不过后者的复杂程度较原来的问题更小。

        权衡(折中):理论可实现与实际可实现。

1.3 编译过程

        编译程序的工作一般可以分为五个阶段:

  •  词法分析:从左至右读源程序(字符流),识别出句子中的一个个单词符号(又称记号token) ;源程序字符序列  → 单词符号序列 。

  • 语法分析:依据源程序的语法规则进行层次分析;单词符号序列  →  分析树(Parse Tree)(或语法树-Syntax Tree) ;语法分析又称解析(Parsing)
Parse Tree
语法树是分析树的压缩表示

  • 语义分析和中间代码产生:语义分析的功能是进行语义检查,即验证语法结构合法的程序是否在语义上正确(程序的各个组成部分组合在一起是否有意义), 需收集代码生成阶段需要的语义信息 ;类型检查与类型转换 ;分析树   →   带语义(注释)的树。
语义分析

        中间代码生成的功能是生成源程序的中间表示。 三地址代码(three address-code); 带语义(注释)的树  → 中间代码 。

 position  =  initial  +  rate  *  60的中间代码:

(1)    (    inttoreal,     60    -    t1    )

(2)    (    *    ,    id3    t1    t2    )

(3)    (    +    ,    id2    t2    t3    )

(4)    (   =    ,    t3    -    id1    )

  • 优化:对中间代码进行优化,以提高目标程序的时间与空间效率; 在此要特别说明的是,这里的代码优化与目标机器无关。

(1)    (inttoreal,    60    -    t1    )

(2)    (    *         ,  id3    t1    t2    )

(3)    (    +         ,   id2      t2      t3      )

(4)    (   =       ,    t3    -    id1    )  

代码优化后:                     

(1) (    * ,id3     60.0     t1)            

( 2)(   + ,id2    t1       id1)

  • 目标代码生成:机器代码(machine code)、可重定位的机器代码(relocatable machine code )、汇编语言代码(assembly code)       

(1) (    * ,id3     60.0     t1)            

( 2)(   + ,id2    t1       id1)

生成:

movf    id3 , R2

mulf    #60.0 , R2

movf    id2 , R1

addf    R2 , R1

movf    R1 , id1

        此外,还有两个贯穿整个编译过程的工作: 符号表管理、 错误处理 

        符号表管理的功能:管理分析过程中得到的源程序中的标识符的各种信息 :记录源程序中使用的标识符(identifier) 收集每个标识符的各种属性(attribute)信息,包括类型(type)、作用域(scope)、存储分配(storage allocated)信息 。

        出错处理的功能: 检查错误的位置 :检查错误的性质(词法、语法、语义…)与 错误恢复

1.4  编译器的分析综合模式

        前端主要由与源语言有关而与目标机器无关的那些部分组成:1. 词法分析、语法分析、符号表的建立、语义分析和中间代码生成 2.与机器无关的代码优化工作 3.相应的错误处理工作和符号表操作

        后端由编译程序中与目标机器有关的部分组成 :1.与机器有关的代码优化、目标代码的生成 2.相应的错误处理和符号表操作

        把编译程序划分成前端和后端的优点: 便于移植、便于编译程序的构造。 

1.5 语言之间的翻译

1.6 编译器扫描的遍数 

        一“遍”是指对源程序或其中间形式从头到尾扫描一遍,并作相关的加工处理,生成新的中间形式或目标程序。 编译程序的结构受“遍”的影响 。分为:一遍扫描的编译程序和 多遍编译程序。
 

一遍扫描的编译程序
多遍编译程序

 1.7 编译程序的前后处理器

1.7.1  预处理器

1.7.1.1预处理器——宏

         预处理器的功能 :宏处理 、文件包含、 语言扩充

        预处理器允许用户在源程序中定义宏。

        C语言源程序中的一个宏定义:  #define  prompt(s)  fprintf(stderr, s)

        宏处理器处理两类语句,即宏定义和宏调用。

          宏定义通常用统一的字符或关键字表示,如define或macro,宏定义由宏名字及宏体组成,通常宏处理器允许在宏定义中使用形参。  

         宏调用由调用宏的命令名(宏名)和所提供的实参组成。宏处理器用实参代替宏体中的形参,再用变换后的宏体替换宏调用本身。

1.7.1.2 预处理器——文件包含

        预处理器把文件的包含声明扩展为程序正文。 例:C语言程序中的“头文件”包含声明行:  #include  <stdio.h> ,预处理器处理到该语句时,就用文件stdio.h的内容替换此语句。

1.7.1.3 预处理器——语言扩充

        有些预处理器用更先进的控制流和数据结构来增强原来的语言。 例如: 预处理器可以将类似于while或if-then-else语句结构的内部宏提供给用户使用,而这些结构在原来的程序设计语言中是没有的。 当程序中使用了这样的结构时,由预处理器通过宏调用实现语言功能的扩充。

1.7.2 汇编程序

1.7.3连接装配程序


下篇:【编译原理】02词法分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值