火速加班加点写了一篇。

今天把函数定义的parser给撸完了,边摸鱼编写代码,真有你的

已经把代码推送到GitHub了。

其实parser挺好写的。

哪为什么某人又咕咕了这么久呢?

当然是因为懒了

不过我还是贴一下函数定义parser的代码吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
pub fn parse_func_decl(&mut self) -> Result<Statement, String> {
let name = self.parse_ident()?;
let mut params: Vec<(String, Behaviour, String)> = Vec::new();

if self.lookahead().kind != TokenKind::LeftParen {
return Err("Expected a '(' after the function name.".into());
}

self.eat(); // eat '('.

while self.lookahead().kind != TokenKind::RightParen {
if self.lookahead().kind == TokenKind::Comma {
self.eat(); // eat ',' between the parameters.
}

let param = {
let param_name = self.parse_ident()?;
let behaviour = self.next_tok_is_op();

if behaviour.is_none() {
return Err("Expected '=', '->' or '<-' after the parameter name".into());
}

let bhv: Behaviour = match behaviour.unwrap() {
BinaryOp::Assign => Behaviour::Copy,
BinaryOp::Ref => Behaviour::Ref,
BinaryOp::Move => Behaviour::Move,
_ => return Err("Expected '=', '->' or '<-' after the parameter name".into()),
};

let ty = self.parse_ident()?;

(param_name.content, bhv, ty.content)
};

params.push(param);
}

self.eat(); // eat ')'.

if self.lookahead().kind != TokenKind::LeftBrace {
return Err("Expected a block as function body after function signature.".into());
}

self.eat(); // eat '{'.

if let Ok(Statement::Block(body)) = self.parse_block() {
Ok(Statement::FuncDecl {
ident: name.content,
params,
body,
})
} else {
Err("Expected a block as function body after function signature.".into())
}
}

差不多就是这样。

然后,测试用的代码:

1
2
3
fn function(a <- int32, b <- int32) {
return a + b;
}

输出很令人满意。但是我总是觉得firelang编译器构建的语法树太过复杂。

输出(因为Rust的”{:#?}”格式化输出十分像json,下面输出的语法树就用json高亮渲染一下。):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
FuncDecl {
ident: "function",
params: [
(
"a",
Move,
"int32",
),
(
"b",
Move,
"int32",
),
],
body: Block {
block: [
Return(
Binary {
lhs: Ident(
"a",
),
op: Add,
rhs: Ident(
"b",
),
},
),
],
},
}

确实好复杂啊……

那么,话就说到这里,大鸽子Ink要去学vm和codegen了。