随想录(推荐《自制编译器》这本书)


【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】


    最近,amazon网站上出现了一本书《自制编译器》,我觉得挺好的,分享给大家。相关地址单击这里。图书的作者是一位日本人,写的很仔细。其实,图灵出版社还引入了一些列的自制书籍,包括《自制cpu》、《自制操作系统》等等,有兴趣的同学都可以找来看看。事实上现在网上这类的资源很多了,只要你想学,基本上都可以满足你的需求。


    读书的时候,虽然编译原理这门考试考的还可以,但是却没有深入理解过这么课。这一次正好利用看这一本书的机会,好好梳理了一下。通常情况下,编译文件分为这几个步骤:词法分析、语法分析、语义分析、中间代码生成、代码生成与优化。词法分析比较简单,主要就是读取文本文件,将文件中的字符串进行归类处理,比如说哪些是关键字、哪些是数字、哪些是字符串、哪些是分割符等等。语法分析稍微复杂一些,它主要是把文本字符串按照当初bnf范式的形式构建成一个合适的语法树,方便后面进行中间代码生成。语义分析一般紧跟着语法分析进行,它主要是检查语法树中是不是存在非法的语句存在,比如变量重复出现、赋值错误、除数为0等等。中间代码比较简单,主要是按照语法树的要求,暂时先将语法树上的if语句、for语句、while语句、block语句转变成四元组,或者是你自己定义的某种临时代码格式,之所以这么做是因为事实上需要将源文件转换成很多种cpu代码,因此必须要先这么做。至此之前的这四个部分可以称之为编译器前端处理,后端处理呢就是将中间代码转变成目标cpu代码。最后一部就是代码生成与优化,arm处理器就转变成arm代码,x86处理器就转变成x86代码,选择不同的转变方式就可以了。同样,生成代码的时候必要的优化也是不可少的,有的是基于运算速度的,有的是基于空间大小的,还有的是基于cpu乱序执行的,这部分内容就很复杂了。总之,优化的目的就是为了除去冗余代码,越快越好。


    早先开发编译器是一件非常辛苦的事情,但是现在就没有那么困难了。书中介绍的工具是javacc,这是一个语法解析工具,用java写成,我自己不太熟悉。对我来说,比较了解的其实还是lex & yacc这两个工具,lex可以帮你进行字符串的梳理,或者叫token的判别,yacc可以帮助你构建一个合适的语法树。这样,有了这两个工具,如果你需要生成目标文件,像C一样,这是可以的。当然你也可以自己设计一个脚本语言,像perl、python一样,没有任何问题。


    最后,我自己尝试在github上找找看,有没有比较简单的c编译器可以练练手,没想到还真的有,地址在这里。这是一个用python写成的简单编译器,你可以自己写一个小的c文件,然后用python解析看看具体的结果是什么。比如,我输入的文件是hello.c,


#include <stdio.h>

int main() {

	return 0;
}


    词法分析的结果是这样的,python compiler.py -s hello.c -l,


(SHARP, #)
(INCLUDE, include)
(LT, <)
(IDENTIFIER, stdio.h)
(GT, >)
(INT, int)
(IDENTIFIER, main)
(LL_BRACKET, ()
(RL_BRACKET, ))
(LB_BRACKET, {)
(RETURN, return)
(DIGIT_CONSTANT, 0)
(SEMICOLON, ;)
(RB_BRACKET, })

    语法分析是这样的, python compiler.py -s hello.c -p


( self: Sentence None, father: None, left: None, right: None )
( self: Include None, father: Sentence, left: None, right: FunctionStatement )
( self: # None, father: Include, left: None, right: include )
( self: include None, father: Include, left: #, right: < )
( self: < None, father: Include, left: include, right: stdio.h )
( self: stdio.h None, father: Include, left: <, right: > )
( self: > None, father: Include, left: stdio.h, right: None )
( self: FunctionStatement None, father: Sentence, left: Include, right: None )
( self: Type None, father: FunctionStatement, left: None, right: FunctionName )
( self: int FIELD_TYPE, father: Type, left: None, right: None )
( self: FunctionName None, father: FunctionStatement, left: Type, right: StateParameterList )
( self: main IDENTIFIER, father: FunctionName, left: None, right: None )
( self: StateParameterList None, father: FunctionStatement, left: FunctionName, right: Sentence )
( self: Sentence None, father: FunctionStatement, left: StateParameterList, right: None )
( self: Return None, father: Sentence, left: None, right: None )
( self: return None, father: Return, left: None, right: Expression )
( self: Expression Constant, father: Return, left: return, right: None )
( self: 0 _Constant, father: Expression, left: None, right: None )

    生成的汇编文件又是这样的,python compiler.py -s hello.c -a,


.data
.bss
.lcomm bss_tmp, 4
.text
.globl main
main:
finit
pushl $0
call exit

    虽然这个python还不能处理嵌套等特别复杂的语法,但是用仅仅1500行的code就能做到这样其实已经是难得可贵了。有兴趣的同学可以去试一试,也可以看看这个compiler.py文件是怎么写的。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式-老费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值