Meow语言开发记录-基础 (1)

哪个程序员不想拥有自己的编程语言呢?对于柠喵来说,也是一样呢,随着柠喵用过的语言越来越多,柠喵也发现了各种语言的优点和缺点,那么为什么不能自己创造一种语言,摒弃它们的缺点,吸收它们的优点呢?是了,这就是这个系列出现的原因,柠喵要亲手实现一门自己的语言,并逐渐完善,而且,还要记录下来,毕竟柠喵也是热爱Open Source的,哦对,说起Open Source,Meow语言的源码也会开放到Github上去,方便大家阅读,顺便,还能给柠喵提建议,多棒啊。

柠喵的目标其实很远大,那就是用自己制作的编程语言制作自己的操作系统,但是,柠喵到目前为止还处于入门阶段,甚至连计算机基础都没学过(还没上大学),这就很麻烦了,没有知识基础,目标是无法实现的,啊,怎么办,只能一步步来了,所以,这个文章系列会从0开始,还包括了学习和掉坑的过程,会非常啰嗦,非常的长,如果你觉得某些部分很啰嗦就跳过去好了。

设计一门编程语言,其实就是设计一个编译器,所以首先要知道编译器该怎么设计,如果是脚本语言,那就是解释器。要设计编译器就要首先知道编译器的工作原理,知道编译器的结构,好像一个小小的目标已经明确了,那么我们开始吧。

编译器的工作原理与结构

所谓编译器就是将源代码编译成可执行程序的程序,它的目标也可以是另一种语言的源代码(比如Kotlin编译成JS),编译器进行编译的步骤大概是:词法分析->语法分析->语义分析->生成中间代码->代码优化->生成目标代码,虽然我用的是箭头表示步骤先后,但是这些步骤不一定是串行执行,有些编译器可以实现并行执行,提高效率。根据编译步骤,编译器又能被分为几个子模块,分别是:词法分析器,语法分析器,语义分析器,代码生成器。(从网上抄下来的)大概就是这样,但是感觉还是没搞懂,词法分析器和语法分析器这些东西又是什么啊?

词法分析器

词法分析器大概就是一个从文本读取字符流,然后输出单词序列的一个东西,将输入的字符流按照一定的规则“切割”成一个个“单词”,比如按照中文语法来“切割”下面的句子:

1
2
3
柠喵在敲代码。

柠喵 在 敲 代码 。

(为了能看清楚柠喵敲了两个空格)。但是仅仅输出单词还不够,还要同时输出这个单词的类型,这样才能继续语法分析,于是可以变成下面这样:

1
2
3
柠喵在敲代码。

(柠喵,代词) (在,介词) (敲,动词) (代码,名词)

词法分析器的输出交给语法分析器去处理。就是这样,感觉好像懂了,下一个,语法分析器又是啥?

语法分析器

之前说了,词法分析的输出结果交给语法分析器处理,那语法分析器的输入就是单词序列了,语法分析器的任务就是读取单词序列,根据语法规则推导出单词序列的语法结构,输出“语法树”,那么一个算式5=3+2可以被处理为:

1
2
3
4
5
  =
/ \
5 +
/ \
3 2

看,是典型的树结构吧,当然这是柠喵的理解,如果错了,希望小伙伴们能指出。
语法分析器的输出会交给语义分析器,两个步骤已完成,进入第三个步骤。

语义分析器

越到后面就越难了,但是这才到语义分析呢。语义分析器接受语法树作为输入,收集语义信息,比如变量定义,同时检查是否有语义错误,比如引用了未定义的标识符或重复定义标识符等,这一步为中间代码生成做准备。嗯,干巴巴的两句说明柠喵理解的也不是很透彻,但是这的确是语义分析器的任务。

代码生成器

代码生成器的任务很多,中间代码生成,代码优化和目标代码生成,代码生成器根据语义分析器生成的语法树(不是词法分析的那个语法树)生成中间代码,中间代码一般由四元式构成,四元式的第一个分量是操作码,剩下三个是操作数,然后再根据生成的四元式生成目标代码,优秀的编译器在生成代码时会进行代码优化,将开销高的运算替换为等价的开销低的运算,将不必要的运算删除等,这样能优化程序运行速度和减少程序体积。

结束

硬着头皮啃书效率还是太低了点,用了一天时间才了解编译器的工作原理和构造,还好柠喵在B站找到了哈工大的编译原理,那可比直接啃书快多了,理解起来也更容易。在真正制作Meow语言之前柠喵还有很多要学习的呢,一步步来,一步一个脚印,当然,只有下过雨的泥巴路那样的路才能留下脚印吧。