抽象语法树(AST)
正如前面提到的,解析器会建立一个结构来表示程序的语义。AST节点是一个普通的JavaScript对象,它有一个类型属性,指定它是什么类型的节点,以及根据特定类型指定的附加信息。
总览:
num
{ type: "num", value: NUMBER }str
{ type: "str", value: STRING }bool
{ type: "bool", value: true or false }var
{ type: "var", value: NAME }lambda
{ type: "lambda", vars: [ NAME... ], body: AST }call
{ type: "call", func: AST, args: [ AST... ] }if
{ type: "if", cond: AST, then: AST, else: AST }assign
{ type: "assign", operator: "=", left: AST, right: AST }binary
{ type: "binary", operator: OPERATOR, left: AST, right: AST }prog
{ type: "prog", prog: [ AST... ] }
- let
{ type: "let", vars: [ VARS... ], body: AST }
例子:
Numbers ("num")
123.5→
{ type: "num", value: 123.5 }Strings ("str")
"Hello World!"→
{ type: "str", value: "Hello World!" }Booleans ("bool")
true
false→
{ type: "bool", value: true }
{ type: "bool", value: false }标识符 ("var")
foo→
{ type: "var", value: "foo" }函数 ("lambda")
lambda (x) 10 # or
λ (x) 10Later we will add an optional "name" property, to support named
functions, but the first version of our parser won't have it.
→
{
type: "lambda",
vars: [ "x" ],
body: { type: "num", value: 10 }
}函数调用 ("call")
foo(a, 1)→
{
"type": "call",
"func": { "type": "var", "value": "foo" },
"args": [
{ "type": "var", "value": "a" },
{ "type": "num", "value": 1 }
]
}条件语句 ("if")
if foo then bar else baz→
{
"type": "if",
"cond": { "type": "var", "value": "foo" },
"then": { "type": "var", "value": "bar" },
"else": { "type": "var", "value": "baz" }
}else 分支是可选的:
if foo then bar→
{
"type": "if",
"cond": { "type": "var", "value": "foo" },
"then": { "type": "var", "value": "bar" }
}赋值 ("assign")
a = 10→
{
"type": "assign",
"operator": "=",
"left": { "type": "var", "value": "a" },
"right": { "type": "num", "value": 10 }
}二进制表达式 ("binary")
x + y * z→
{
"type": "binary",
"operator": "+",
"left": { "type": "var", "value": "x" },
"right": {
"type": "binary",
"operator": "*",
"left": { "type": "var", "value": "y" },
"right": { "type": "var", "value": "z" }
}
}序列 ("prog")
{
a = 5;
b = a * 2;
a + b;
}→
{
"type": "prog",
"prog": [
{
"type": "assign",
"operator": "=",
"left": { "type": "var", "value": "a" },
"right": { "type": "num", "value": 5 }
},
{
"type": "assign",
"operator": "=",
"left": { "type": "var", "value": "b" },
"right": {
"type": "binary",
"operator": "*",
"left": { "type": "var", "value": "a" },
"right": { "type": "num", "value": 2 }
}
},
{
"type": "binary",
"operator": "+",
"left": { "type": "var", "value": "a" },
"right": { "type": "var", "value": "b" }
}
]
}拥有块作用域的变量 ("let")
let (a = 10, b = a * 10) {
a + b;
}在我们第一版的编译器将不会有这个节点类型,我们会在之后加入这一特性。
→
{
"type": "let",
"vars": [
{
"name": "a",
"def": { "type": "num", "value": 10 }
},
{
"name": "b",
"def": {
"type": "binary",
"operator": "*",
"left": { "type": "var", "value": "a" },
"right": { "type": "num", "value": 10 }
}
}
],
"body": {
"type": "binary",
"operator": "+",
"left": { "type": "var", "value": "a" },
"right": { "type": "var", "value": "b" }
}
}