Legend Since 1984
Cruising between Fantasy and Reality...

Saturday, June 10, 2006

Why not make a compiler yourself

时间是凌晨3点05分,还有30个小时就是编译原理考试了。复习还处在攻坚阶段,而现在的我,却为自己的一个想法激动得难以入眠。

编译原理课程的5个实验我都是一步步兢兢业业走过来的,通过这五个实验,一套简单的编译器前端已经初具雏形。这个前端接受三个输入文件:文法产生式集合、关键字集合、待翻译原程序,输出了翻译后的四元式。

我自己最为满意的部分就是语法分析表的自动构建。不管是采用哪种语法分析策略(自顶向下、自底向上),我都费了很大的功夫在分析表的自动构建上面。现在看来,这笔投入是相当划算的。有了分析表的自动构建,我可以随意修改输入语言的文法构成而不必重新手工计算修改后语言的分析表(这是一个相当大计算量的工作,如果人脑完成的话)。在作语义分析的时候,为了验证我设计的翻译方案和属性的存放方法,通常是采用一个非常简单的文法来进行验证。有了前面工作的基础,在更换文法的时候,我要做的仅仅是替换那三个编译前端接受的输入文件——文法产生式集合、关键字集合、待翻译原程序;在配以相应的语义动作处理函数重新编译,我的前段就可以正常工作了。(实际上,如果不做语义分析的话,甚至连程序都不用重新编译就可以直接运行)。尤其是在采用自顶向下的语义分析时,属性的存放方式经历了较大的变化,每次变化都先采用一个简单的“计算器”文法进行了验证。还有后来对原文法进行了修改,使之改成了类C语言的定义规则,还加入了控制循环的break、continue语句的实现。这些改变都没有对原来程序的语法分析部分作任何的修改。

以下两图是两种分析策略分别的结构图。尽管他们采用的方法有所差异,但是最终的输出都是一致的——未经过优化的标准四元式及程序内部符号表。



图表 1:自底向上分析器的整体结构


图表 2:自顶向下分析器的整体结构

这是课程设计的终点,也许绝大多数人到了这里也就停下了。但是我想做得更多!前面的工作已经有了很好的开端——功能上我已经实现了分析表的自动构造,实现上我也没松懈:首先是采用面向对象从数据结构入手模块化的设计思想,每个类完成特定的功能、封装内部数据成员、依靠函数接口对外提供服务;各模块内聚性高,添加功能容易;编程语言采用最高效的C++而不是Java或者C#等使用方便但效率低下的基于虚拟机的语言;采用STL作为容器的实现,既高效又节省了大量精力;后期在实现上也作了一些优化,能用简单数据类型的地方尽量不用复杂的容器类,利用C++的异常来处理产生的编译错误,代码中使用宏来力求简洁,多次重构力求代码扼要而优雅;……

这些基础都是对后续工作的铺垫。我的梦想是完成一个完整的编译器,至少能输出通用格式的汇编代码。虽说从四元式到汇编只有一步之遥,但要想做到功能的完整还有很多难关需要攻克。最艰巨的要数支持函数调用。仅仅这一个名词下就包含的很多东西:运行时环境、活动记录、参数传递、局部变量与全局变量的访问、函数返回等。其他的还有对数组的支持、汇编代码的格式。初拟的一份TO DO List如下:

表格 1:Compiler DIY 's TO DO List

功能描述相关概念/说明
函数调用运行时环境、活动记录、参数传递、局部变量与全局变量的访问、函数返回
数组是否使用指针的形式、相应的翻译方案
更多数据类型指针、结构体、数组、浮点数
浮点数词法分析器
符号表的扩充内情向量、相对地址
非终结符的扩充把原先采用单个大小写字符作为非终结符的方式改为以一个字符串来标示
输出汇编格式Windows下:cl /Fa(VC++)、Linux下gcc –S(gcc)
标准IO可能需要用汇编编写、或者连接现成的库函数
错误处理忽略错误继续编译

如果能全部完成以上功能也就是一个较为完整的编译器成品了,但是我很明白这不是一个短期内可以完成的任务。明白前方的障碍才是前进的基石。也许,我可以申请把它作为毕业设计来完成吧。

一直以来,编译器就是令我感到神秘而向往的东西。如今,一个自己独立实现的编译器已经不再那么遥不可及了。什么才是计算机科学的基石?不管现在各种流行技术怎么发展,试问哪门语言的运行离得开后台编译器的支持?Java,PHP,C#,Perl,JSP?如果说操作系统是连接计算机硬件和软件的桥梁,那么编译器就是沟通操作系统与高级语言的纽带;如果把操作系统比作谁与争锋的倚天剑,那么编译器绝对是号令江湖的屠龙刀!

现在回到床上,在梦中给我未来的编译器想个诱人的名字才是当前最重要的~~~Zzzzz

Labels: ,

0 Comments:

Post a Comment

<< Home