编译原理-引论
引论
1.1
编译器和解释器
source-to-source 的翻译器
:一种高级语言翻译为另一种高级语言的编译器.
汇编器(assembler)
:
与处理器(preprocessor)
:
链接器(linker)
:
加载器(loader)
:将可制行目标文件方式内存中执行
编译器的目标:
- 将源程序翻译为目标程序
- 在翻译过程中发现源程序的错误
- java 程序的执行过程”java 源程序编译成字节码,然后虚拟机对字节码进行解释执行.
1 区别是什么?
编译器
将程序编译为目标程序,然后直接执行目标程序解释器
直接执行程序 2 各自相对的优点是什么?编译器相对于解释期的优点
:代码检查可以在执行前检查,编译后的代码可以进行优化相对性能更好.解释器相对编译器的优点
:可以即时运行,不需要编译阶段- 编译器产生汇编语言而不是机器语言的好处是什么? a.(2022.1030)由于不同的机器的底层实现存在一定差别,使用编译器产生汇编语言后可以在不同的机器或者系统上运行,从而实现跨系统 b.(2022.1031) 汇编程序可以更好的进行输出和调试
- 编译器使用目标语言有什么好处?
- 描述一下汇编器要完成的任务. 词法分析->语法分析->生成中间代码->优化->生产汇编代码
1.2 编译器的结构
分析(front end):将源程序分解成多个组成要素,在组成要素中加入语法结构. 检查语法错误,返回错误信息,供用户更改,收集有关程序的信息,将信息存在符号表中,符号表和中间新会市一起传送给综合部分.
符号表
综合(back end): 构造目标过程
词法分析(lexical analysis)(scanning):
将字符流组成有意义的词素序列,词法分析器产生词法单元(token)
作为输出
<token-name,attribute-value> token-name 是词法分析中使用的抽象符号,attribute-value 是窒息感符号表中关于这个词法单元的条目,符号表条目会被语法分析和代码生成的步骤使用
position=initial+rate*60
语法分析(syntax analysis)(parsing)
词法分析器生成的各个词法单元的第一个分量来创建树形结构的中间表示,常用的表示方法是语法树.
语法树 syntax tree
:
语义分析(semantic analyzer)
使用语法树和符号表中的信息来检查源程序是否和语言定义的语义一致
类型检查(type checking)
语义分析的重要部分是类型检查
自动类型转换(coercion)
中间代码生成
三地址代码(three-address code)
- 每个三地址赋值指令的右部分最多只有一个运算符,因此这些指令确定了运算完成的顺序
- 编译器应该生成临时敏子存放三地址指令生成的计算的值
- 有些三地址指令预算分量少于三个
代码优化
- 代码优化的目的一般是让代码更快
代码生产
符号表管理
记录程序中变量使用的名字,并收集每个名字的属性相关信息
- 存储分配
- 类型
- 作用域
- 参数数量和类型
- 每个参数的传递方法(传值还是传引用)
- 返回类型
将多个步骤组合成趟
编译器构造工具
三类参数传递机制的区别
- 传值调用(call-by-value) 一般情况下,传值调用会把表达式求值,变量拷贝传递给相应过程,因此相应实参不会修改.但是传递的变量为指针时会被调用者改变,在java 中 数组 x[2]=i 这样的赋值 语句会改变 数组元素x[2].
- 传引用调用(call-by-address) 因为拷贝代价太大,有的高级程序语言会使用传引用调用,java 运行时对 不是基本类型的参数进行引用调用.
- 传名调用(call-by-name)
在scala 中使用call-by-name 时,参数每次使用会重新计算
上下文无关文法 ` context-free grammer` 组成元素: 一个终结符号集合 一个非终结符号集合 一个产生式集合 一个非中介符号的开始符号 词法单元由名字和属性值组成,词法单元的名字是进行分析时产生的中间符号,我们将这些词法单元的名字称为终结符号,词法单元的属性值是指向符号表的指针.在进行词法分析时不考虑符号表,所以我们通常将词法单元和终结符号当做同义词