- 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和=已经成功解析。