根据 《Create your own compiler》实现的编译器
https://citw.dev/tutorial/create-your-own-compiler
简单实现一个编译器 compiler
函数,实现把 Lisp
语法 转化为 JavaScript
语法
示例:
(add 2 (sub 4 3)) // Lisp
add(2,sub(4,3)) // JavaScript
了解 AST
https://zhaomenghuan.js.org/blog/js-ast-principle-reveals.html#%E5%89%8D%E8%A8%80
NodeJS
以及 npm包管理器,如 npm
/yarn
/pnpm
https://github.com/TonicFizzRicky/create-compiler.git
# 安装依赖
pnpm i
# 开发打包代码(ts -> js)
pnpm dev
# 运行代码
pnpm start
代码:src/tokenizer.ts
将代码字符串逐字进行拆解,分析词法
生成一个对象数组 token
对象数组的 type
约定如下
paren: 符号(如:括号)
name: 变量或者函数的名称
number: 数字
词法分析生成 token
:
[
{ type: 'paren', value: '(' },
{ type: 'name', value: 'add' },
{ type: 'number', value: '2' },
{ type: 'paren', value: '(' },
{ type: 'name', value: 'sub' },
{ type: 'number', value: '4' },
{ type: 'number', value: '3' },
{ type: 'paren', value: ')' },
{ type: 'paren', value: ')' }
]
代码:src/parser.ts
上一步生成的 token
需要进行语法分析,主要通过 type
进行转化
转化为一个树状结构的 lisp AST
(lisp 语言的抽象语法树)
通过树状结构我们可以知道函数调用的参数以及类型,相较于 token
更具语义化
CallExpression
表示这个类型为函数表达式,CallExpression
使用 name
存储函数的名称
NumberLiteral
表示这个类型为数字类型,使用 value
存储值
// (add 2 (sub 4 3))
// add 函数被调用,参数为 2 以及 sub(4,3)
// sub 函数被调用 参数为 4,3
{
"type": "Program",
"body": [
{
"type": "CallExpression",
"name": "add",
"params": [
{
"type": "NumberLiteral",
"value": "2"
},
{
"type": "CallExpression",
"name": "sub",
"params": [
{
"type": "NumberLiteral",
"value": "4"
},
{
"type": "NumberLiteral",
"value": "3"
}
]
}
]
}
]
}
代码:src/transformer.ts
上一步得到的 lisp AST
,转化为 js AST
可以参考: https://astexplorer.net/
其实不生成 js AST
也能直接通过 lisp AST
去转化 js代码
至于为什么需要经过 Transformation
这一步处理,还需要再梳理一下逻辑
{
"type": "Program",
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "add"
},
"arguments": [
{
"type": "NumericLiteral",
"value": "2"
},
{
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "sub"
},
"arguments": [
{
"type": "NumericLiteral",
"value": "4"
},
{
"type": "NumericLiteral",
"value": "3"
}
]
}
]
}
}
]
}
代码:src/generateCode.ts
根据 js AST
生成 js code
- 补充类型声明