TinyC编译器4—编译器基本流程

1.什么是编译器,为什么要开发编译器

编译器:将一种程序语言翻译为另一种程序语言的计算机程序。一般来说,源程序为高级语言,而目标语言则是汇编语言或者机器码。

一开始的程序员是用机器码写程序,非常容易出错,后来开始使用汇编语言开始写,但是依旧不高效,后来在50-60年代,有人发明了高级语言及编译器,这就导致写程序就像写数学公式推理一样,方便了很多。所以开发编译器是很重要的。

2.编译器的工作流程

  • 对源文件进行扫描,将源文件的字符流拆解成一个个的词(记号),此为词法分析
  • 根据语法规则,将这些记号构造成语法树,此为语法分析
  • 对语法树各个结点之间的关系进行检查,检查语义规则是否被违背,同时对语法树进行必要的优化,此为语义分析
  • 遍历语法树的结点,将各个结点转换成中间代码,并按照特定的顺序拼装起来,此为中间代码生成
  • 对中间代码进行优化
  • 将中间代码转换成目标代码
  • 对目标代码进行优化,生成最终的目标程序

2.1词法分析

编译器扫描源文件的字符流,过滤掉字符流中的空格、注释等,并将其分割成一个个的词(记号、token)。

a = value + sum(5, 123);

将被拆分为11个 token :

a           标识符
=           赋值运算符
value       标识符
+           加号
sum         标识符
(           左括号
5           整数
,           逗号
123         整数
)           右括号
;           分号

2.2语法分析

词法分析完成后,上面的字符流就被转换为 token 流了:

ID<a> '=' ID<value> '+' ID<sum> '(' NUM<5> ',' NUM<123> ')' ';'

上面的 ID<a> 表示这一个标识符类型的 token ,其内容为 a。其他的赋值符号等全都用‘’

其实不难看出,语法分析其实就是不断拆解一个语句,形成一个语法树。

2.3语义分析

就是在遍历语法树的过程中,遇到变量声明和函数声明时,则将变量名——类型、函数名——返回类型——参数数量及类型等信息保存到符号表里,当遇到使用变量和函数的地方,则根据名称在符号表中查找和检查,查找该名称是否被声明过,该名称的类型是否被正确的使用等等。

其实本质就是一个检查防止错误的过程。

2.4中间代码生成

  • 中间代码不仅有一些高级语言的特性,也有接近机器语言的部分,所以相当于一个中间过渡态。这样就可以实现从高级语言代码->中间代码->目标代码,而且这比高级语言代码->目标代码简单很多。
  • 增加编译器的模块化、可移植性和可扩展性。一般来说,中间代码既独立于任何高级语言,也独立于任何目标机器架构,这就为开发出适应性广泛的编译器提供了媒介。

如下图中,可以通过编写 m + n 个编译模块而获得 m * n 种编译器。

2.5中间代码优化

编译器对中间代码进行优化,尝试生成体积最小、最快、最有效率的代码。

  • 去除永远都不会被执行的代码区
  • 去掉未被使用到的变量
  • 优化循环体,将每次循环中的运行结果不变的语句移到循环的最外面
  • 算术表达式优化,将乘 1 和 加 0 等操作去掉,将乘 2 优化成左移 1 位等

2.6编译过程的错误检查

词法、语法和语义分析的过程中,都伴随着错误检查,词法错误主要是字符错误(如非法字符、未结束的注释、未结束的字符串等),语法错误主要是格式错误(如语句后未加分号、不匹配的括号等),最常发生的是语义错误(如变量名错误、表达式类型错误、函数参数不匹配等)。编译器不仅检查错误,还需要精确定位出错误发生的位置,协助编程人员修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值