教程资源
入门教程在:手把手教你做一个 C 语言编译器
学习过程
19年尝试学了一下,中途看不懂放弃了。20年底从头再看一遍,经过一年的知识积累,在仔细研读之下,终于算是学懂了。此文中记录了我在最初学习时遇到的问题,和最终的解决方法记录下来,希望对读者有所帮助。
虚拟机
虚拟机涉及的知识是比较综合性的,是一个难点。虚拟机的原理是,模拟实现CPU的指令集。CPU的指令功能无非就是操作存储和调用运算资源,我们完全可以自己模拟实现。这样我们就可以不生成直接运行在电脑上的机器码,不用关心exe文件格式,而是实现一个简单的虚拟机来把源码当做脚本来执行。如此,机器码生成的任务可以大大减少,降低入门难度。
BNF
刚开始学的时候遇到的问题是,弄不懂BNF。BNF只有弄懂了,才会自己写,才会用代码实现。个人对BNF的理解见我的另一篇博客:编译原理—理解BNF。
逻辑流程图
在脑海中要有一张如下图的逻辑流程图:
其中,符号表特别重要,源码中的重要信息都是保存在符号表中的。
要特别说一下,比较容易纠结的问题是,为什么按照上面的流程先解析Token,再语法分析,就可以解析代码了?知其然还要知其所以然。我的理解是,编程语言在设计的时候,就考虑到,一要能准确无误的表达出一个操作,没有歧义;二是为了能使编译器更易于实现。编程语言并不是一下子就设计好的,很可能是在设计编译器的过程中不断丰富完善的。举一个例子:为什么标识符不能以数字开头?因为,如果标识符以数字开头,编译过程中就需要更多的判断来分辨到底是一个标识符还是一个数字或者表达式,直接规定不允许以数字开头,保证了不同类型的Token起始符号不同,就可以很容易判断Token的类型了。
动手实践
在原教程的基础上,可以自己尝试实现具有更强功能的C语言脚本,如支持结构体解析,如在解析代码的基础上,实现编辑器上下文提示等等。
同时,在对编译原理上下文无关文法的理解的基础上,学习其他语言,应该更加容易。
同时,可以自己开发一些小工具用来对代码进行自定义处理。
更加深入
后续可以学习已有脚本语言的实现原理,甚至可以尝试自己开发一款脚本语言,学无止境,再接再厉!