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


© 2021-2022 | 柴树杉 保留所有权利