Parser:读出谓词和 if
本节阅读量:
上一节已经确定目标 AST:
1
2
|
Eq(lhs, rhs)
If(condition, then_branch, else_branch)
|
第三章的 lexer 不需要新增规则。它仍然只给括号补空格,再按空白切 token。
例如:
会切成:
1
|
["(", "if", "(", "eq?", "0", "0", ")", "42", "7", ")"]
|
eq? 读取两个表达式
1
2
3
4
5
6
7
|
if (head == "eq?") {
advance();
auto lhs = parse_expr();
auto rhs = parse_expr();
expect(")", "expected ')' after eq? expression");
return std::make_unique<EqExpr>(std::move(lhs), std::move(rhs));
}
|
左右两边都可以是任意表达式。判断某个表达式是不是 0,直接写成:
if 读取三个表达式
1
2
3
4
5
6
7
8
9
10
11
|
if (head == "if") {
advance();
auto condition = parse_expr();
auto then_branch = parse_expr();
auto else_branch = parse_expr();
expect(")", "expected ')' after if expression");
return std::make_unique<IfExpr>(
std::move(condition),
std::move(then_branch),
std::move(else_branch));
}
|
parser 必须把 condition、then 和 else 都读完,才能得到完整 AST。但“解析时读出两个分支”不等于“运行时求值两个分支”:parser 在这里不计算 condition,也不做选择,只把三个位置原样保存在 AST 里。
identifier 规则没有变化
普通变量名仍然沿用第二章的 letter+,parser 不需要修改 is_identifier()。
eq? 和 if 都在左括号后的 head 位置按固定形式识别。尤其是 eq?:问号属于这段固定拼写,并没有扩大普通变量名的范围。
这也延续了第二章的解析方式:parser 根据列表 head 判断当前结构,而不是让 lexer 把每个特殊形式变成新的 token 类型。
试一下
1
2
3
4
|
cd code/03_conditionals
make
./mini ast examples/eq.lang
./mini ast examples/if.lang
|
if.lang 的输出是:
1
|
If(Eq(Int(0), Int(0)), Int(42), Int(7))
|
到这里,新增源码已经能稳定变成 AST。下一节让解释器执行它。