Introductory Notes on Compilation Principles
编译原理
这个文档是伴随着我开发 mendax 编程语言而写的,所以会插入部分和编译原理无关的知识。
所谓的编译原理,就是让计算机理解更高级的语言并执行。将问题抽象化处理,若仅局限于低级机器语言,则很难产生面向对象和函数式等编程思想。以此可以给人提供更好的思考方式。
面向对象:面向对象编程——Object Oriented Programming,简称 OOP,是一种程序设计思想。OOP 把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
函数式(参考自阮一峰老师的网络日志):
数学表达式:(1 + 2) * 3 - 4
面向过程:
var a = 1 + 2;
var b = a * 3;
var c = b - 4;
函数式:
var result = subtract(multiply(add(1,2),3),4);
词法分析
程序的源代码最初只是一长串字符串。从内部来看,源代码中的换行也能用专门的(不可见)换行符表示,因此整个源代码是一种相连的长字符串。这样的长字符串很难处理,语言处理器通常会首先将字符串中的字符以单词为单位分组,切割成多个子字符串。这就是词法分析。就像是去除了程序中无用的内容,筛选出了有价值的信息。
要设计词法分析器,首先要考虑每一种类型的单词的定义,规定怎样的字符串才能构成一个单词。这里最重要的是不能有歧义。某个特定的字符串只能是某种特定类型的单词。举例来讲,要是字符串 123h 既能被解释为标识符,又能被解释为整型字面量,之后的处理就会相当麻烦。这种单词的定义方式是不可取的。
词法分析的结果在数学上是一个元组,例如整数 13,可以这么表示 (13, Integer)。
var x = 10 + 2 * 4
-->
// 数学 - 元组 Token
var: Keyword
a: Variable // 编程语言本身提供的具有特殊功能的词语
=: Operator
10: Integer
+: Operator
2: Integer
*: Operator
24: Integer
简而言之,词法分析是一个分析断句和判断词性的过程
字母表:语言 L 所允许的所有字符。
串:语言 L 字母表的一个有穷序列(允许空串)。不可能所有的串都是语言支持的,因此我们通常用一些约束规则来描述串,其中就有正则表达式。
状态机
将多个状态机合并成词法分析器
编译器制作过程中我们通常用正则表达式来表述词法,然后用状态机来实现正则表达式。
—— INSERT ——
javascript 的 this 语法
流
一般情况,流需要提供获取下一个数据的接口。next() 方法读取到下一个数据之后,这个数据就相当于流过去了,因此无法重复读取。
在 JavaScript 中如果一段代码运行超过一次,那么就称为 warm。如果一个函数开始变得 warmer(注:即运行更多次),JIT 将把这段代码送到编译器中编译并且保存一个编译后的版本。下一次同样代码执行的时候,引擎会跳过翻译过程直接使用编译后的版本。
—— END
语法分析
抽象语法树
1 + 2 * 3 + 4 的表达式的抽象语法树
上下文无关文法
在不需要理解某个语言的前提下,给定任意这门语言的句子,便可以得到一个合理的抽象语法树。
非终结符(递归)函数:parseExpr(生成一个非叶子结点) 终结符:parseNumber(生成一个叶子结点)