34

编译原理入门课:(前言)实现一个表达式解析计算器

 3 years ago
source link: http://blog.harrisonxi.com/2019/07/%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86%E5%85%A5%E9%97%A8%E8%AF%BE%EF%BC%9A%EF%BC%88%E5%89%8D%E8%A8%80%EF%BC%89%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%E8%AE%A1%E7%AE%97%E5%99%A8.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

编译原理入门课:(前言)实现一个表达式解析计算器

2019-07-01编译原理

首先要聊聊我为什么想要写一篇编译原理的入门课。熟悉我的人可能会知道,我喜欢把复杂难懂的东西拆解成简单易理解的东西,无论是在代码的设计上,还是在知识的分享上。另外我也是个实用主义者,写出来的代码光好看没有什么卵用,必须要有实际的用途,它才是有价值的代码。所以写这样一个系列的博客,主要有两个目的:

  1. 拆解编译原理里一部分入门级别的基础知识,用最少的篇幅讲解编译器前端的大致工作原理
  2. 实现一个可以解析并计算简单数学表达式的库,让需要的人可以使用它完成一些计算功能

所谓编译器前端,主要是指词法分析、语法分析这一类解析的过程,负责把我们写的代码翻译成计算机可以理解的格式。编译器后端,主要负责把前端解析得到的中间代码进行优化,生成CPU可以运行的二进制代码。编译器后端的知识,需要对汇编、计算机组成原理之类的知识有一定了解,才能更好的理解。所以我在这里不太打算深入讲解编译器后端的知识,想要全面了解编译原理的同学可以参考别的教程进行学习。

曾经尝试学习过编译原理的同学,可能会深有感触,抱着书啃起来很枯燥,很容易从入门到放弃。编译原理的三大著名书籍人称龙书、虎书、鲸书,具体书名大家自己搜一下就很容易找到。我们比较熟悉的一本应该就是下图这个龙书——《编译原理》,普及最广应该是因为翻译得比较好吧。书里说的大部分是理论知识,很可能看完三四章后,了解了很多编译器中的概念和方法,但是想要自制个编译器就会觉得无从下手。不过这不会影响它的地位,想深入学习编译原理肯定还是离不开它的,建议对编译器感兴趣的同学先从博客入门,入门后如果觉得想要更深入,再买一本《编译原理》回去啃也不迟。

01-A

推荐博客及开源库

首推一个lotabout大佬的《手把手教你构建 C 语言编译器》系列博客。博客从构建虚拟机开始,然后逐步的介绍词法分析再到语法分析,围绕着已经构建好的虚拟机一步步构造编译器。从构造编译器的过程上来说,大概是下图这样:

01-B

lotabout大佬的教程总结起来有以下特点:

  1. 编译器完整:包含编译器前端和编译器后端,对了解编译器完整工作流程有很大帮助

  2. 功能丰富:支持变量,条件和循环语句等复杂功能

  3. 较为深入:对虚拟机设计的讲解,以及对应虚拟机的代码生成逻辑都讲得较为深入。这个有好有坏,好处当然是大家能学到的东西更多,坏处就是对于不了解CPU和汇编的同学来说太难理解

  4. 中期无法运行:教程中期几篇的结尾都会有“本章的代码还无法正常运行”。这是必然的,编译器必须完成完整的流程才能运行,在虚拟机的基础上没有完成生成代码的逻辑,肯定会无法运行。这就可能让中间的学习过程有一定的断层

推荐的开源库首先也是推荐lotabout大佬博客对应的GitHub开源库:write-a-C-interpreter。光对着代码干啃很累,有对应的博客当然还是学起来更快的。

然后推荐的是Fabrice Bellard大神的otcc,这应该是最迷你的C语言编译器了,迷你但五脏俱全,甚至于可以做到自举(自举就是自己可以编译自己)。它是当年Fabrice Bellard参加国际混淆(混乱)C语言代码大赛的获奖作品,可以编译C语言的子集。当然我们阅读代码的时候请阅读非混淆版本的,不然你的大脑可能得跟计算机一样才能看懂写得是什么……

想再深入学习代码就试着看TinyCC吧,是Fabrice Bellard基于otcc扩展写出来的完整的C语言编译器,号称最快最小。这个级别的代码,反正我已经看不懂了……

我这里要写的入门课,一开始就说了不包含编译器后端,所以这里不能叫它编译器,只能叫做解释器或者说计算器。和大部分的编译原理课不同,我会先写出来可以运行的最小单元,然后一边展开知识范围一边迭代,让解释器可以支持更多的功能。大概的过程会是这样:

01-C

是不是更像是一个软件的常规迭代过程些?入门课会有以下特征:

  1. 只含编译器前端,功能只有简单计算,简化了要学习的内容
  2. 始终可以运行,持续迭代新功能

目录会如下:

(一)用最简单的语法分析器解析加减法

(二)递归解析中怎么处理运算符优先级

(三)简单错误处理逻辑以及负数的解析

(四)用词法解析处理多位数字和空白符

(五)解析ID型词法和函数调用语法

后面还可能会补充其他内容,要看看大家对什么内容/功能感兴趣,还要等我的懒癌被治好。

入门课对应的代码都会开源放在GitHub:SlimeExpressionC

想要更多的功能/教学可以在我的博客里留言,或者到对应的开源库下面去提issue,也热烈欢迎你们提MR或者fork出去自己玩。今天就先水到这里。

01-D


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK