编译器一日一练(DIY系列之开篇)
Posted 嵌入式-老费
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器一日一练(DIY系列之开篇)相关的知识,希望对你有一定的参考价值。
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
编译原理这门课,很多计算机专业的同学都学过。但是学的怎么样,就看每个人自己了。和操作系统、计算机组成原理、计算机网络一样,很多学校都把编译原理当成了文科、理科来学,这就大错特错了。计算机专业本来就属于工科,工科的重要特点就是理论和实际相结合。理论是原理、方法、算法,实际就是动手操作。没有实际的操作,理论是不可能领会的。
编译原理的步骤,大家都比较熟悉,就是词法分析、语法分析、语义分析、中间代码生成、优化和生成汇编这几个步骤。但是每个步骤怎么做的,不知道大家有没有实践过没?如果做过,那么大家有没有看过实际语言的代码,比如python的编译器代码、lua的代码、甚至是c的代码?
1、相信自己肯定可以学会
编译器的基础理论虽然来自于数学,但是并不难掌握。实践过程中可以从简单的开始学,比如四则表达式、简单的c编译器开始写起。有问题不害怕,就是要在写的过程中发现和解决问题,这样自己肯定才可以提高。
我知道,很多学校编译原理的实践课,写一个词法分析就是及格,一个语法分析就是优秀,如果能完成中间代码生成,那绝对是非常出色了。但是这离编写完整的编译器还有一段距离,所以一定要动手实践,多思考,相信自己一定可以学会的。
2、先精通一门语言
了解编译原理,最好先精通一门语言。然后在这个基础之上,再次查看这个语言是怎么解析的。对于自己不熟悉的语言,往往花费的时间更长一点,走的冤枉路会多一点,而且会挫伤个人的学习积极性。
3、汇编边学边看
很多同学害怕汇编,不管是x86,还是arm、mips、powerpc,甚至是java字节码这些,都觉的是非常高深的东西,这大可不必。本着用到什么学什么的策略,只学习自己需要的汇编就可以了,多多练习之后就会发现汇编也就这么回事。
4、了解运行环境
所谓的运行环境,主要就是函数调用和堆栈分配这部分。临时变量怎么处理,入参怎么处理,出参怎么处理,默认bind的寄存器是什么,这个了解一下就好。
5、熟练使用第三方工具
很多同学不知道,现在设计和编写一门语言比原来容易多了。比如前端部分就可以用flex完成词法分析、bison完成语法分析,后端用llvm生成汇编代码。可能有的同学还以为,编写编译器要像gcc那样,是一个巨细无比的工作,事实上不是这样的。编译器不仅仅有gcc,还有很多小的编译器和脚本语言。就像操作系统不仅仅有linux,还有ucos这样很多的小操作系统。
就算不喜欢flex、bison这样的工具,还有javacc、python的ply,每个同学选择自己擅长的工具就好了。这样,我们做的东西就不仅仅是玩具,而是实实在在可以发挥作用的生产力软件。
6、克服畏惧心理,挑选几个成熟的编译器阅读
这方面的编译器很多,代码少一点的有lua、python和golang。其实lua是蛮不错的一门语言,如果看最新的版本有困难,可以去看早期的版本。
7、充分运用现有编译器的编译选项
我们都知道,编译器分成语法、语义、中间代码、汇编等步骤,那么我们就可以把语法树ast、中间代码ir、汇编代码打印出来。此外,编译器常常带有很多的优化功能,那就把优化之前的汇编代码和优化之后的汇编代码打印出来比较下就好了,这方面只要按着步骤去做,学习的速度其实是非常快速的,比单纯地去记忆基本原理要好很多。
8、实践理论相结合
理论一般是比较纯粹的,实际则复杂的多。比如说,编译器语法分析有自顶向下LL和自底向上LR两种,那么实际编译器使用哪一种呢。答案其实就是两种都用。比如,一般语法就用LL递归,表达式就用LR移进规约。所以在实际编译器当中,充满了各种技巧和妥协,有的时候还是很有意思的。
至于文法部分,也不用紧张。复杂难理解的,可以先从简单的看起,正则表达式就是最基础的文法,很适合用来入门。
9、调试编译器
编译器也是软件,调试编译器就和调试普通软件是一样的,不要觉得是多么了不起的事情。但是这个事情一定要去做。有的时候,出现困惑也是正常的。比如,为啥golang的编译器也是用golang写的?gcc的编译器居然是gcc自己,这个到底是为什么?一时想不明白,可以把这个问题放在脑海里,有空就拿出来思考一下。
其他:
编写编译器也有很多的工具,比如lex、bison、后端llvm等等。编写过程中也有很多的方法,比如错误日志、语法树打印、中间代码查看、汇编查看等等,所以其实只要慢慢做,其实都都是可以学会、学懂的。
以上是关于编译器一日一练(DIY系列之开篇)的主要内容,如果未能解决你的问题,请参考以下文章