AST:给条件和分支留位置

本节阅读量:

前两章已经有:

1
2
3
4
Int(value)
Add(lhs, rhs)
Var(name)
Let(name, value, body)

第三章新增:

1
2
Eq(lhs, rhs)
If(condition, then_branch, else_branch)

ExprKind 增加两类

代码在:

1
2
code/03_conditionals/src/front/ast.h
code/03_conditionals/src/front/ast.cpp

表达式分类现在是:

1
2
3
4
5
6
7
8
enum class ExprKind {
    integer,
    add,
    variable,
    let,
    equal,
    conditional,
};

解释器和 lowerer 仍然读取 kind,再用 switch 处理不同节点。第三章只是增加分类,没有改变前两章的分派方式。

EqExpr 保存左右两个表达式

1
2
3
4
5
6
7
struct EqExpr final : Expr {
    EqExpr(std::unique_ptr<Expr> lhs, std::unique_ptr<Expr> rhs);

    std::unique_ptr<Expr> lhs;
    std::unique_ptr<Expr> rhs;
    std::string dump() const override;
};

例如:

1
(eq? (+ 20 22) 42)

对应:

1
Eq(Add(Int(20), Int(22)), Int(42))

IfExpr 明确保留三个位置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
struct IfExpr final : Expr {
    IfExpr(std::unique_ptr<Expr> condition,
           std::unique_ptr<Expr> then_branch,
           std::unique_ptr<Expr> else_branch);

    std::unique_ptr<Expr> condition;
    std::unique_ptr<Expr> then_branch;
    std::unique_ptr<Expr> else_branch;
    std::string dump() const override;
};

源码:

1
(if (eq? 0 0) 42 7)

AST:

1
If(Eq(Int(0), Int(0)), Int(42), Int(7))

三个子表达式的位置不能混:

1
2
3
condition     决定选择哪条路
then_branch   条件非 0 时求值
else_branch   条件为 0 时求值

观察 AST

1
2
3
cd code/03_conditionals
make
./mini ast examples/if.lang

输出:

1
If(Eq(Int(0), Int(0)), Int(42), Int(7))

下一节看 parser 怎样生成这些节点。


3.1 从顺序计算到条件选择

上一节

3.3 Parser:读出谓词和 if

下一节