- KusonStack一站式可编程配置技术栈(Go): https://github.com/KusionStack/kusion
- KCL 配置编程语言(Rust): https://github.com/KusionStack/KCLVM
- 凹语言™: https://github.com/wa-lang/wa
4.1 完善token包
在开始改造编译器之前,我们先深刻理解本章新出现语法的细节。
4.1.1 变量定义
为了简化问题,我们目前只支持以下几种形式的变量定义:
var x1 int
var x2 int = 134
var x3 = 456
其中x1只有类型,没有初始化值,初始为0值。x2指定类型并通过一个表达式初始化。x3则忽略类型,只有一个初始化表达式。每个var只能定义一个变量。目前假设变量全部都是int类型,底层为32bit的整数。因为涉及全局变量的初始化,最终需要隐式产生一个init函数用于全局变量的初始化工作。
4.1.2 嵌套作用域
遍历支持嵌套作用域,内层同名的变量自动屏蔽外层的变量:
package main
var x int
func main() {
x = x + 1
var x int = x + 10
{
println(x)
var x = x + 100
println(x)
}
println(x)
}
其中x = x + 1
是对main包的x变量加一。var x int = x + 10
则是在main函数内重新定义一个局部变量,并用外层的包级的x变量进行初始化。最后一个var x = x + 100
是在内层定义一个同名的x变量,并用main函数之前定义x变量进行初始化。
4.1.3 定义新的Token类型
本章的例子只新增加了var
关键字和=
赋值操作符。token包增加以下定义:
package token
// 记号类型
type TokenType int
// ch3中 µGo程序用到的记号类型
const (
EOF TokenType = iota // = 0
...
VAR // var
ASSIGN // =
...
)
同时需要将VAR注册为关键字类型,便于配合token.Lookup
函数工作。
4.1.4 完善Token方法
token.Token表示一个记号的纸:
type Token struct {
Pos Pos // 记号所在的位置(从1开始)
Type TokenType // 记号的类型
Literal string // 程序中原始的字符串
}
主要是Token出现的位置、Token类型和对应的面值字符串。
对于整数类型的Token,我们还需要将其面值字符串解析为整数值。因此为其定义一个IntValue方法:
func (i Token) IntValue() int {
x, err := strconv.ParseInt(i.Literal, 10, 64)
if err != nil {
panic(err)
}
return int(x)
}
如果后面要支持float和string类型时,我们也可以增加对应的辅助方法。
4.1.5 完善lex包
两个记号的词法解析比较简单。补全词法解析后,解析以下代码:
package main
func main() {
var x = 1 + 2
}
输出结果如下:
$ go run main.go -debug=false lex ./_examples/hello.ugo
00: package : "package" // ./_examples/hello.ugo:1:1
01: IDENT : "main" // ./_examples/hello.ugo:1:9
02: ; : "" // ./_examples/hello.ugo:2:1
03: func : "func" // ./_examples/hello.ugo:3:1
04: IDENT : "main" // ./_examples/hello.ugo:3:6
05: ( : "(" // ./_examples/hello.ugo:3:10
06: ) : ")" // ./_examples/hello.ugo:3:11
07: { : "{" // ./_examples/hello.ugo:3:13
08: var : "var" // ./_examples/hello.ugo:4:2
09: IDENT : "x" // ./_examples/hello.ugo:4:6
10: = : "=" // ./_examples/hello.ugo:4:8
11: NUMBER : "1" // ./_examples/hello.ugo:4:10
12: + : "+" // ./_examples/hello.ugo:4:12
13: NUMBER : "2" // ./_examples/hello.ugo:4:14
14: ; : "" // ./_examples/hello.ugo:5:1
15: } : "}" // ./_examples/hello.ugo:5:1
16: EOF : "" // ./_examples/hello.ugo:6:1
其中var
和=
已经成功解析。