《Go语言定制指南》:本站后置篇:《Go语言定制指南》-编译篇
一、词法单元
高级语言由许多基本元素构成,基本元素就是词法单元。词法单元构成表达式和语句;表达式和语句构成函数;函数构成源文件;源文件构成软件工程项目。
词法单元三个重要属性:类型、在源代码中的原始文本形式、出现的位置。(特殊的注释和分号可忽略)
1.1 词法单元简介
Go语言中的词法单元分为标识符(包括25个关键字)、运算符和分隔符等几类。
自定义标识符 |
25个关键字 |
47个运算符和分隔符 |
字面量 |
注释 |
空白符 |
|
1
2
|
identifier = letter { letter | unicode_digit } .
letter = unicode_letter | "_" .
|
1.2 Token定义
源代码参考go/token
包中的token.Token
枚举表示,分为特殊类型、基础字面量、操作符和关键字大类。
类别 |
举例 |
特殊类型 |
错误ILLEGAL、EOF文件结束、注释COMMENT |
基础字面量 |
IDENT、INT、FLOAT、IMAG、CHAR、STRING |
操作符 |
ADD、SUB、MUL… |
关键字 |
BREAK、CASE、CHAN、CONST… |
各种大类之间有枚举值表示开始和结束,用于判断具体类型属于哪个大类,例如literal_beg
和literal_end
之间的都属于字面量类型。
解读:
- 基础字面量仅包含整数、浮点数、复数、符文和字符串,不包含true和false。
- 运算符:算数运算符、逻辑运算符、位运算符和比较运算符、取址运算符、管道运算符等;分隔符:圆括号、花括号、方括号、逗号、圆点、分号和冒号。
1.3 FileSet和File
每个FileSet表示一个文件集合,底层抽象为一个一维数组,而Pos类型表示数组的下标位置。FileSet中的每个File元素对应底层数组的一个区间,不同的File之间没有交集,相邻的File之间可能存在填充空间。
File的组成
文件名 |
base |
size |
文件名 |
对应File在FileSet中的Pos索引位置 |
文件大小 |
File内部通过offset
定位下标索引,通过File.base+offset
可以将内部的offset转换为FileSet的Pos位置。
1.4 解析Token
使用标准库的go/scanner.Scanner
实现Token扫描,包含Init方法和Scan方法,Init指定目标文件、源码字节、错误处理和扫描模式;Scan方法逐个扫描得到具体位置、词法单元和原始字符串
1
2
3
4
5
6
7
8
9
10
|
type Scanner struct {
ErrorCount int // number of errors encountered
}
func (s *Scanner) Init(
file *token.File, src []byte,
err ErrorHandler, mode Mode,
)
func (s *Scanner) Scan() (
pos token.Pos, tok token.Token, lit string,
)
|
使用样例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package main
import (
"fmt"
"go/scanner"
"go/token"
)
func main() {
var src = []byte(`println("你好,世界")`)
var fset = token.NewFileSet()
var file = fset.AddFile("hello.go", fset.Base(), len(src))
var s scanner.Scanner
s.Init(file, src, nil, scanner.ScanComments)
for {
pos, tok, lit := s.Scan()
if tok == token.EOF {
break
}
fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
}
}
|
1
2
3
4
5
|
hello.go:1:1 IDENT "println"
hello.go:1:8 ( ""
hello.go:1:9 STRING "\"你好,世界\""
hello.go:1:26 ) ""
hello.go:1:27 ; "\n"
|
1.5 Position位置信息
go/token.Position
表示更详细的位置信息,fset.Position(pos)
可获得对应位置的信息。
二、基础字面量
2.1 基础面值
2.1.1 定义
例如整数的定义(十进制、二进制、八进制和十六进制)
1
2
3
4
5
|
int_lit = decimal_lit | binary_lit | octal_lit | hex_lit .
decimal_lit = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] .
binary_lit = "0" ( "b" | "B" ) [ "_" ] binary_digits .
octal_lit = "0" [ "o" | "O" ] [ "_" ] octal_digits .
hex_lit = "0" ( "x" | "X" ) [ "_" ] hex_digits .
|
完整定义参考基础面值定义
2.1.2 基础面值语法树结构
go/ast.BasicLit
表示一个基础类型的面值常量结构,开始的字节偏移量、面值类型和原始代码字符串
1
2
3
4
5
|
type BasicLit struct {
ValuePos token.Pos // literal position
Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
Value string // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
}
|
2.1.3 手动构造面值
1
2
3
4
5
6
7
8
9
10
11
12
|
package main
import (
"go/ast"
"go/token"
)
func main() {
var lit9527 = &ast.BasicLit{
Kind: token.INT,
Value: "9527",
}
ast.Print(nil, lit9527)
}
|
2.1.4 解析基础面值
使用go/parser.PaseExpr
函数解析
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`9527`)
ast.Print(nil, expr)
}
|
1
2
3
4
5
|
0 *ast.BasicLit {
1 . ValuePos: 1
2 . Kind: STRING
3 . Value: "\"9527\""
4 }
|
通过基础面值、指针、结构体、数组和map等其他语法解构的互相嵌套可以构造其他复杂类型。
2.2 标识符面值
2.2.1 结构
1
2
3
4
5
|
type Ident struct {
NamePos token.Pos // identifier position
Name string // identifier name
Obj *Object // denoted object; or nil
}
|
2.2.2 手动构造
1
2
3
|
func main() {
ast.Print(nil, ast.NewIdent(`x`))
}
|
2.2.3 解析标识符面值
1
2
3
|
func main() {
ast.Print(nil, ast.NewIdent(`x`))
}
|
1
2
3
4
5
6
7
8
|
0 *ast.Ident {
1 . NamePos: 1
2 . Name: "x"
3 . Obj: *ast.Object {
4 . . Kind: bad
5 . . Name: ""
6 . }
7 }
|
ast.Object
是一个相对复杂的结构,其中Kind用于描述标识符的类型,Bad
表示未知的类型
三、基础表达式
基础表达式是指完全由数值型面值和标识符组成的表达式。
3.1 基础表达式语法
1
2
3
4
5
6
7
8
9
10
|
Expression = UnaryExpr | Expression binary_op Expression .
UnaryExpr = Operand | unary_op UnaryExpr .
Operand = Literal | identifier | "(" Expression ")" .
binary_op = "||" | "&&" | rel_op | add_op | mul_op .
rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" .
add_op = "+" | "-" | "|" | "^" .
mul_op = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" .
unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
|
其中Expression表示基础表达式的递归定义,可以是UnaryExpr类型的一元表达式,或者是binary_op生成的二元表达式。而基础表达式运算符两边的对象由Operand定义,主要是面值或表达式,也可以是由小括弧包含的表达式。
3.2 解析表达式
parser.ParseExpr
函数解析返回ast.Expr
抽象接口
1
2
3
4
5
6
7
8
|
type Expr interface {
Node
// contains filtered or unexported methods
}
type Node interface {
Pos() token.Pos // position of first character belonging to the node
End() token.Pos // position of first character immediately after the node
}
|
具体表达式类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$ go doc go/ast | grep Expr
type BadExpr struct{ ... }
type BinaryExpr struct{ ... }
type CallExpr struct{ ... }
type Expr interface{ ... }
type ExprStmt struct{ ... }
type IndexExpr struct{ ... }
type KeyValueExpr struct{ ... }
type ParenExpr struct{ ... }
type SelectorExpr struct{ ... }
type SliceExpr struct{ ... }
type StarExpr struct{ ... }
type TypeAssertExpr struct{ ... }
type UnaryExpr struct{ ... }
|
解析代码实例
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`1+2*3`)
ast.Print(nil, expr)
}
|
其中ast.BinaryExpr
表示二元表达式的节点,包含两个Expr类型的操作数(可递归)、以及Token类型的操作符
1
2
3
4
5
6
|
type BinaryExpr struct {
X Expr // left operand
OpPos token.Pos // position of Op
Op token.Token // operator
Y Expr // right operand
}
|
3.3 表达式求值
基础字面量ast.BasicLit
是特殊的表达式,如果是二元表达式则根据操作符将操作数进行对应的求值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
func main() {
expr, _ := parser.ParseExpr(`1+2*3`)
fmt.Println(Eval(expr))
}
func Eval(exp ast.Expr) float64 {
switch exp := exp.(type) {
case *ast.BinaryExpr:
return EvalBinaryExpr(exp)
case *ast.BasicLit:
f, _ := strconv.ParseFloat(exp.Value, 64)
return f
}
return 0
}
func EvalBinaryExpr(exp *ast.BinaryExpr) float64 {
switch exp.Op {
case token.ADD:
return Eval(exp.X) + Eval(exp.Y)
case token.MUL:
return Eval(exp.X) * Eval(exp.Y)
}
return 0
}
|
3.4 带变量的表达式求值
标识符ast.Indent
也是表达式,,在求值是带上一个上下文参数,从上下文中获取对应标识符的变量值,进行求值
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
|
func main() {
expr, _ := parser.ParseExpr(`1+2*3+x`)
fmt.Println(Eval(expr, map[string]float64{
"x": 100,
}))
}
func Eval(exp ast.Expr, vars map[string]float64) float64 {
switch exp := exp.(type) {
case *ast.BinaryExpr:
return EvalBinaryExpr(exp, vars)
case *ast.BasicLit:
f, _ := strconv.ParseFloat(exp.Value, 64)
return f
case *ast.Ident:
return vars[exp.Name]
}
return 0
}
func EvalBinaryExpr(exp *ast.BinaryExpr, vars map[string]float64) float64 {
switch exp.Op {
case token.ADD:
return Eval(exp.X, vars) + Eval(exp.Y, vars)
case token.MUL:
return Eval(exp.X, vars) * Eval(exp.Y, vars)
}
return 0
}
|
四、代码结构
4.1 目录结构
parser.ParseDir
解析目录内的全部Go语言文件,parser.ParseFile
解析单个文件
_test为后缀会自动生成独立的测试包
4.2 文件结构
源文件由包定义、导入声明和顶级声明三个部分组成
1
2
3
4
5
6
7
8
9
10
11
|
SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
PackageClause = "package" PackageName .
PackageName = identifier .
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
Declaration = ConstDecl | TypeDecl | VarDecl .
|
使用parser.ParseFile
解析单个文件实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("package:", f.Name)
for _, s := range f.Imports {
fmt.Println("import:", s.Path.Value)
}
for _, decl := range f.Decls {
fmt.Printf("decl: %T\n", decl)
}
}
const src = `package pkgname
import ("a"; "b")
type SomeType int
const PI = 3.14
var Length = 1
func main() {}
`
|
返回的类型为*ast.File
类型,File.Imports
属性对应导入信息,File.Decls
属性对应声明;其中import、type、const和var都对应ast.GenDecl
类型,函数是独立的ast.FuncDecl
类型
1
2
3
4
5
6
7
8
9
10
|
type File struct {
Doc *CommentGroup // associated documentation; or nil
Package token.Pos // position of "package" keyword
Name *Ident // package name
Decls []Decl // top-level declarations; or nil
Scope *Scope // package scope (this file only)
Imports []*ImportSpec // imports in this file
Unresolved []*Ident // unresolved identifiers in this file
Comments []*CommentGroup // list of all comments in the source file
}
|
4.3 诊断语法树
go/ast
包提供了ast.Print
函数用于打印语法树,以及ast.Walk
遍历语法树(或使用包装函数ast.Inspect
遍历)。
4.4 总结
五、通用声明
5.1 导入声明
1
2
3
4
5
|
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
PackageName = identifier .
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.ImportsOnly)
if err != nil {
log.Fatal(err)
}
for _, s := range f.Imports {
fmt.Printf("import: name = %v, path = %#v\n", s.Name, s.Path)
}
}
const src = `package foo
import "pkg-a"
import pkg_b_v2 "pkg-b"
import . "pkg-c"
import _ "pkg-d"
`
|
其中parser.ImportsOnly
标识仅解析导入包的部分
1
2
3
4
|
import: name = <nil>, path = &ast.BasicLit{ValuePos:20, Kind:9, Value:"\"pkg-a\""}
import: name = pkg_b_v2, path = &ast.BasicLit{ValuePos:44, Kind:9, Value:"\"pkg-b\""}
import: name = ., path = &ast.BasicLit{ValuePos:61, Kind:9, Value:"\"pkg-c\""}
import: name = _, path = &ast.BasicLit{ValuePos:78, Kind:9, Value:"\"pkg-d\""}
|
5.2 基础类型声明
1
2
3
4
5
6
|
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
AliasDecl = identifier "=" Type .
TypeDef = identifier Type .
Type = identifier | "(" Type ")" .
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
log.Fatal(err)
}
...
}
const src = `package foo
type MyInt1 int
type MyInt2 = int
`
|
返回的所有声明都在f.Decls
列表中,基础声明对应的类型时*ast.GenDecl
类型,其中可以通过GenDecl.Specs查看具体的节点元素的类型,例如*ast.TypeSpec
1
2
3
4
5
6
7
|
type TypeSpec struct {
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
Assign token.Pos // position of '=', if any
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
Comment *CommentGroup // line comments; or nil
}
|
Name
:新声明类型的名字或则已有类型的别名。Assign
:对应=符号的位置,位置有效则标识已有类型的别名。Type
:表示具体类型的表达式。
5.3 常量声明
1
2
3
4
5
|
ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
|
解析目标代码样例
1
2
|
const Pi = 3.14
const E float64 = 2.71828
|
ast.GenDecl.Specs
类型为*ast.ValueSpec
类型
1
2
3
4
5
6
7
|
type ValueSpec struct {
Doc *CommentGroup // associated documentation; or nil
Names []*Ident // value names (len(Names) > 0)
Type Expr // value type; or nil
Values []Expr // initial values; or nil
Comment *CommentGroup // line comments; or nil
}
|
因为Go支持多赋值表达式,所以Names和Values均为列表,Type用于区分常量是否指定了强类型。
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
|
0 *ast.ValueSpec {
1 . Names: []*ast.Ident (len = 1) {
2 . . 0: *ast.Ident {
3 . . . NamePos: 19
4 . . . Name: "Pi"
5 . . . Obj: *ast.Object {
6 . . . . Kind: const
7 . . . . Name: "Pi"
8 . . . . Decl: *(obj @ 0)
9 . . . . Data: 0
10 . . . }
11 . . }
12 . }
13 . Values: []ast.Expr (len = 1) {
14 . . 0: *ast.BasicLit {
15 . . . ValuePos: 24
16 . . . Kind: FLOAT
17 . . . Value: "3.14"
18 . . }
19 . }
20 }
0 *ast.ValueSpec {
1 . Names: []*ast.Ident (len = 1) {
2 . . 0: *ast.Ident {
3 . . . NamePos: 35
4 . . . Name: "E"
5 . . . Obj: *ast.Object {
6 . . . . Kind: const
7 . . . . Name: "E"
8 . . . . Decl: *(obj @ 0)
9 . . . . Data: 0
10 . . . }
11 . . }
12 . }
13 . Type: *ast.Ident {
14 . . NamePos: 37
15 . . Name: "float64"
16 . }
17 . Values: []ast.Expr (len = 1) {
18 . . 0: *ast.BasicLit {
19 . . . ValuePos: 47
20 . . . Kind: FLOAT
21 . . . Value: "2.71828"
22 . . }
23 . }
24 }
|
5.4 变量声明
1
2
3
4
5
|
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
VarSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
log.Fatal(err)
}
for _, decl := range f.Decls {
if v, ok := decl.(*ast.GenDecl); ok {
fmt.Printf("token: %v\n", v.Tok)
for _, spec := range v.Specs {
ast.Print(nil, spec)
}
}
}
}
const src = `package foo
var Pi = 3.14
`
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
token: var
0 *ast.ValueSpec {
1 . Names: []*ast.Ident (len = 1) {
2 . . 0: *ast.Ident {
3 . . . NamePos: 17
4 . . . Name: "Pi"
5 . . . Obj: *ast.Object {
6 . . . . Kind: var
7 . . . . Name: "Pi"
8 . . . . Decl: *(obj @ 0)
9 . . . . Data: 0
10 . . . }
11 . . }
12 . }
13 . Values: []ast.Expr (len = 1) {
14 . . 0: *ast.BasicLit {
15 . . . ValuePos: 22
16 . . . Kind: FLOAT
17 . . . Value: "3.14"
18 . . }
19 . }
20 }
|
5.5 按组声明
1
2
|
XxxDecl = "xxx" ( XxxSpec | "(" { XxxSpec ";" } ")" ) .
XxxSpec = ...
|
语法树的逻辑结构图
六、函数声明
6.1 函数的语法
1
2
3
4
5
6
7
8
9
10
|
FunctionDecl = "func" MethodName Signature [ FunctionBody ] .
MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] .
MethodName = identifier .
Receiver = Parameters .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
|
- Function函数定义:func字符串 函数名称 函数签名 可选的函数体
- Method方法定义:func字符串 接受者 函数名称 函数签名 可选的函数体
6.2 函数
包一级的函数只有包函数和方法两种类型(闭包函数只能在函数体内部创建),而包函数可以看作是没有接收者的方法函数。
解析以下代码得到函数对应的声明类型*ast.FuncDecl
1
|
func (p *xType) Hello(arg1, arg2 int) (bool, error) { ... }
|
1
2
3
4
5
6
7
|
type FuncDecl struct {
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil for external (non-Go) function
}
|
其中输入参数和返回值又被封装为ast.FuncType
类型;对于没有接收者的包函数,ast.FuncDecl.Recv部分为nil。
6.3 参数分组
- 接收者、输入和返回值参数均由
ast.FieldList
定义
FieldList
其实时[]*Field
结构的再次包装
Field
可以表示一组相同类型的参数,例如func Hello1(s0, s1 string, s2 string)
1
2
3
4
5
6
7
8
9
10
11
12
|
type FieldList struct {
Opening token.Pos // position of opening parenthesis/brace, if any
List []*Field // field list; or nil
Closing token.Pos // position of closing parenthesis/brace, if any
}
type Field struct {
Doc *CommentGroup // associated documentation; or nil
Names []*Ident // field/method/parameter names; or nil
Type Expr // field/method/parameter type
Tag *BasicLit // field tag; or nil
Comment *CommentGroup // line comments; or nil
}
|
七、复合类型
复合类型包含其它包中的基础类型(需要通过点号选择操作符)、指针类型、 数组类型、切片类型、结构体类型、map类型、管道类型、函数类型和接口类型,以及它们之间再次组合产生的更复杂的类型。
7.1 类型语法
1
2
3
4
5
6
7
8
9
10
11
12
|
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
AliasDecl = identifier "=" Type .
TypeDef = identifier Type .
Type = TypeName | TypeLit | "(" Type ")" .
TypeName = identifier | PackageName "." identifier .
TypeLit = PointerType | ArrayType | SliceType
| StructType | MapType | ChannelType
| FunctionType | InterfaceType
.
|
TypeName表示当前包的类型标识符或则其他包的类型;TypeLit表示类型面值(比如已有类型的指针或则匿名结构体)
类型定义
1
2
3
4
5
6
7
|
type TypeSpec struct {
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
Assign token.Pos // position of '=', if any; added in Go 1.9
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of th *XxxTypes
Comment *CommentGroup // line comments; or nil
}
|
Type通过特殊的类型表达式表示类型的定义;Assign被设置则表明时类型的别名
7.2 基础类型
1
2
3
4
5
6
7
|
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
AliasDecl = identifier "=" Type .
TypeDef = identifier Type .
Type = identifier | PackageName "." identifier .
|
对已有的类型的包装
1
2
|
type Int1 int
type Int2 pkg.Int
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
log.Fatal(err)
}
for _, decl := range f.Decls {
ast.Print(nil, decl.(*ast.GenDecl).Specs[0])
}
}
const src = `package foo
type Int1 int
type Int2 pkg.int
`
|
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
|
0 *ast.TypeSpec {
1 . Name: *ast.Ident {
2 . . NamePos: 18
3 . . Name: "Int1"
4 . . Obj: *ast.Object {
5 . . . Kind: type
6 . . . Name: "Int1"
7 . . . Decl: *(obj @ 0)
8 . . }
9 . }
10 . Assign: 0
11 . Type: *ast.Ident {
12 . . NamePos: 23
13 . . Name: "int"
14 . }
15 }
0 *ast.TypeSpec {
1 . Name: *ast.Ident {
2 . . NamePos: 32
3 . . Name: "Int2"
4 . . Obj: *ast.Object {
5 . . . Kind: type
6 . . . Name: "Int2"
7 . . . Decl: *(obj @ 0)
8 . . }
9 . }
10 . Assign: 0
11 . Type: *ast.SelectorExpr {
12 . . X: *ast.Ident {
13 . . . NamePos: 37
14 . . . Name: "pkg"
15 . . }
16 . . Sel: *ast.Ident {
17 . . . NamePos: 41
18 . . . Name: "int"
19 . . }
20 . }
21 }
|
7.3 指针类型StarExpr
1
2
3
4
5
|
PointerType = "*" BaseType .
BaseType = Type .
Type = TypeName | TypeLit | "(" Type ")" .
...
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
log.Fatal(err)
}
for _, decl := range f.Decls {
ast.Print(nil, decl.(*ast.GenDecl).Specs[0])
}
}
const src = `package foo
type IntPtr *int
`
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
0 *ast.TypeSpec {
1 . Name: *ast.Ident {
2 . . NamePos: 18
3 . . Name: "IntPtr"
4 . . Obj: *ast.Object {
5 . . . Kind: type
6 . . . Name: "IntPtr"
7 . . . Decl: *(obj @ 0)
8 . . }
9 . }
10 . Assign: 0
11 . Type: *ast.StarExpr {
12 . . Star: 25
13 . . X: *ast.Ident {
14 . . . NamePos: 26
15 . . . Name: "int"
16 . . }
17 . }
18 }
|
新的类型*ast.StarExpr
表示指针类型
1
2
3
4
|
type StarExpr struct {
Star token.Pos // position of "*"
X Expr // operand
}
|
多级指针
1
2
3
4
5
6
7
8
9
10
11
12
|
type IntPtrPtr **int
11 . Type: *ast.StarExpr {
12 . . Star: 28
13 . . X: *ast.StarExpr {
14 . . . Star: 29
15 . . . X: *ast.Ident {
16 . . . . NamePos: 30
17 . . . . Name: "int"
18 . . . }
19 . . }
20 . }
|
7.4 数组类型ArrayType
1
2
3
|
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = Type .
|
解析实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
0 *ast.TypeSpec {
1 . Name: *ast.Ident {
2 . . NamePos: 18
3 . . Name: "IntArray"
4 . . Obj: *ast.Object {
5 . . . Kind: type
6 . . . Name: "IntArray"
7 . . . Decl: *(obj @ 0)
8 . . }
9 . }
10 . Assign: 0
11 . Type: *ast.ArrayType {
12 . . Lbrack: 27
13 . . Len: *ast.BasicLit {
14 . . . ValuePos: 28
15 . . . Kind: INT
16 . . . Value: "1"
17 . . }
18 . . Elt: *ast.Ident {
19 . . . NamePos: 30
20 . . . Name: "int"
21 . . }
22 . }
23 }
|
数据类型对应的类型为*ast.ArrayType
1
2
3
4
5
|
type ArrayType struct {
Lbrack token.Pos // position of "["
Len Expr // Ellipsis node for [...]T array types, nil for slice types
Elt Expr // element type
}
|
Len:数组长度表达式;Elt:元素类型表达式
多重数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
11 . Type: *ast.ArrayType {
12 . . Lbrack: 32
13 . . Len: *ast.BasicLit {
14 . . . ValuePos: 33
15 . . . Kind: INT
16 . . . Value: "1"
17 . . }
18 . . Elt: *ast.ArrayType {
19 . . . Lbrack: 35
20 . . . Len: *ast.BasicLit {
21 . . . . ValuePos: 36
22 . . . . Kind: INT
23 . . . . Value: "2"
24 . . . }
25 . . . Elt: *ast.Ident {
26 . . . . NamePos: 38
27 . . . . Name: "int"
28 . . . }
29 . . }
30 . }
|
7.5 切片类型ArrayType
切片和数组的差异就是省略了数组的长度而已。
1
2
|
SliceType = "[" "]" ElementType .
ElementType = Type .
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
0 *ast.TypeSpec {
1 . Name: *ast.Ident {
2 . . NamePos: 18
3 . . Name: "IntSlice"
4 . . Obj: *ast.Object {
5 . . . Kind: type
6 . . . Name: "IntSlice"
7 . . . Decl: *(obj @ 0)
8 . . }
9 . }
10 . Assign: 0
11 . Type: *ast.ArrayType {
12 . . Lbrack: 27
13 . . Elt: *ast.Ident {
14 . . . NamePos: 29
15 . . . Name: "int"
16 . . }
17 . }
18 }
|
*ast.ArrayType
可以表示数组和切片,通过Len长度成员是否为nil判断
7.6 结构体类型StructType
1
2
3
4
5
6
7
|
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName .
Tag = string_lit .
IdentifierList = identifier { "," identifier } .
TypeName = identifier | PackageName "." identifier .
|
解析实例
1
2
3
4
|
type MyStruct struct {
a, b int "int value"
string
}
|
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
|
11 . Type: *ast.StructType {
12 . . Struct: 27
13 . . Fields: *ast.FieldList {
14 . . . Opening: 34
15 . . . List: []*ast.Field (len = 2) {
16 . . . . 0: *ast.Field {
17 . . . . . Names: []*ast.Ident (len = 2) {
18 . . . . . . 0: *ast.Ident {
19 . . . . . . . NamePos: 37
20 . . . . . . . Name: "a"
21 . . . . . . . Obj: *ast.Object {...}
26 . . . . . . }
27 . . . . . . 1: *ast.Ident {
28 . . . . . . . NamePos: 40
29 . . . . . . . Name: "b"
30 . . . . . . . Obj: *ast.Object {...}
35 . . . . . . }
36 . . . . . }
37 . . . . . Type: *ast.Ident {
38 . . . . . . NamePos: 42
39 . . . . . . Name: "int"
40 . . . . . }
41 . . . . . Tag: *ast.BasicLit {
42 . . . . . . ValuePos: 46
43 . . . . . . Kind: STRING
44 . . . . . . Value: "\"int value\""
45 . . . . . }
46 . . . . }
47 . . . . 1: *ast.Field {
48 . . . . . Type: *ast.Ident {
49 . . . . . . NamePos: 59
50 . . . . . . Name: "string"
51 . . . . . }
52 . . . . }
53 . . . }
54 . . . Closing: 66
55 . . }
56 . . Incomplete: false
57 . }
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
type StructType struct {
Struct token.Pos // position of "struct" keyword
Fields *FieldList // list of field declarations
Incomplete bool // true if (source) fields are missing in the Fields list
}
type FieldList struct {
Opening token.Pos // position of opening parenthesis/brace, if any
List []*Field // field list; or nil
Closing token.Pos // position of closing parenthesis/brace, if any
}
type Field struct {
Doc *CommentGroup // associated documentation; or nil
Names []*Ident // field/method/parameter names; or nil
Type Expr // field/method/parameter type
Tag *BasicLit // field tag; or nil
Comment *CommentGroup // line comments; or nil
}
|
ast.Field
不仅可以表示结构体成员,也可以表示结构方法列表、函数或方法的各种参数列表
7.7 Map类型MapType
1
2
|
MapType = "map" "[" KeyType "]" ElementType .
KeyType = Type .
|
解析实例
1
|
type IntStringMap map[int]string
|
1
2
3
4
5
6
7
8
9
10
11
|
11 . Type: *ast.MapType {
12 . . Map: 31
13 . . Key: *ast.Ident {
14 . . . NamePos: 35
15 . . . Name: "int"
16 . . }
17 . . Value: *ast.Ident {
18 . . . NamePos: 39
19 . . . Name: "string"
20 . . }
21 . }
|
1
2
3
4
5
|
type MapType struct {
Map token.Pos // position of "map" keyword
Key Expr
Value Expr
}
|
其中Key和Value部分都是类型表达式,可以是其它更复杂的组合类型。
7.8 管道类型ChanType
1
|
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
|
1
2
3
4
5
6
7
8
9
10
11
|
type ChanType struct {
Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-"); added in Go 1.1
Dir ChanDir // channel direction
Value Expr // value type
}
type ChanDir int
const (
SEND ChanDir = 1 << iota
RECV
)
|
ast.ChanType.Dir
是管道的方向,SEND表示发送、RECV表示接收、SEND|RECV比特位组合表示双向管道。
解析实例
1
2
3
4
5
6
7
8
9
|
11 . Type: *ast.ChanType {
12 . . Begin: 26
13 . . Arrow: 0
14 . . Dir: 3
15 . . Value: *ast.Ident {
16 . . . NamePos: 31
17 . . . Name: "int"
18 . . }
19 . }
|
7.9 函数类型FuncType
1
2
3
4
5
6
|
FunctionType = "func" Signature .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
|
1
|
type FuncType func(a, b int) bool
|
7.10 接口类型InterfaceType
1
2
3
4
5
6
7
|
InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
MethodSpec = MethodName Signature | InterfaceTypeName .
MethodName = identifier .
InterfaceTypeName = TypeName .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
|
解析实例
1
2
3
|
type IntReader interface {
Read() int
}
|
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
|
11 . Type: *ast.InterfaceType {
12 . . Interface: 28
13 . . Methods: *ast.FieldList {
14 . . . Opening: 38
15 . . . List: []*ast.Field (len = 1) {
16 . . . . 0: *ast.Field {
17 . . . . . Names: []*ast.Ident (len = 1) {
18 . . . . . . 0: *ast.Ident {
19 . . . . . . . NamePos: 41
20 . . . . . . . Name: "Read"
21 . . . . . . . Obj: *ast.Object {
22 . . . . . . . . Kind: func
23 . . . . . . . . Name: "Read"
24 . . . . . . . . Decl: *(obj @ 16)
25 . . . . . . . }
26 . . . . . . }
27 . . . . . }
28 . . . . . Type: *ast.FuncType {
29 . . . . . . Func: 0
30 . . . . . . Params: *ast.FieldList {
31 . . . . . . . Opening: 45
32 . . . . . . . Closing: 46
33 . . . . . . }
34 . . . . . . Results: *ast.FieldList {
35 . . . . . . . Opening: 0
36 . . . . . . . List: []*ast.Field (len = 1) {
37 . . . . . . . . 0: *ast.Field {
38 . . . . . . . . . Type: *ast.Ident {
39 . . . . . . . . . . NamePos: 48
40 . . . . . . . . . . Name: "int"
41 . . . . . . . . . }
42 . . . . . . . . }
43 . . . . . . . }
44 . . . . . . . Closing: 0
45 . . . . . . }
46 . . . . . }
47 . . . . }
48 . . . }
49 . . . Closing: 52
50 . . }
51 . . Incomplete: false
52 . }
|
1
2
3
4
5
6
7
8
9
10
|
type InterfaceType struct {
Interface token.Pos // position of "interface" keyword
Methods *FieldList // list of methods
Incomplete bool // true if (source) methods are missing in the Methods list
}
type StructType struct {
Struct token.Pos // position of "struct" keyword
Fields *FieldList // list of field declarations
Incomplete bool // true if (source) fields are missing in the Fields list
}
|
7.11 组合类型
通过不同组合生成更复杂的类型
八、复合面值
非基础面值包含函数面值和复合类型面值。
8.1 面值语法
完整面值由Literal定义
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
CompositeLit = LiteralType LiteralValue .
LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
SliceType | MapType | TypeName .
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
ElementList = KeyedElement { "," KeyedElement } .
KeyedElement = [ Key ":" ] Element .
Key = FieldName | Expression | LiteralValue .
FieldName = identifier .
Element = Expression | LiteralValue .
|
其中BasicLit是基础面值,CompositeLit是复合面值,FunctionLit是函数面值
8.2 函数面值FunctionLit
1
|
FunctionLit = "func" Signature FunctionBody .
|
解析实例
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`func(){}`)
ast.Print(nil, expr)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
0 *ast.FuncLit {
1 . Type: *ast.FuncType {
2 . . Func: 1
3 . . Params: *ast.FieldList {
4 . . . Opening: 5
5 . . . Closing: 6
6 . . }
7 . }
8 . Body: *ast.BlockStmt {
9 . . Lbrace: 7
10 . . Rbrace: 8
11 . }
12 }
|
函数面值由*ast.FunctionLit
结构体表示,其中Type成员表示类型,Body表示函数体
1
2
3
4
5
6
7
8
9
10
11
|
type FuncLit struct {
Type *FuncType // function type
Body *BlockStmt // function body
}
type FuncDecl struct {
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil for external (non-Go) function
}
|
8.3 复合类型面值CompositeLit
复合类型主要包含结构体、数组、切片和map类型
1
2
3
4
5
6
7
8
9
|
CompositeLit = LiteralType LiteralValue .
LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
SliceType | MapType | TypeName .
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
ElementList = KeyedElement { "," KeyedElement } .
KeyedElement = [ Key ":" ] Element .
Key = FieldName | Expression | LiteralValue .
FieldName = identifier .
Element = Expression | LiteralValue .
|
1
2
3
4
5
6
7
|
[1]int{1}
[...]int{100:1,200:2}
[]int{1,2,3}
[]int{100:1,200:2}
struct {X int}{1}
struct {X int}{X:1}
map[int]int{1:1, 2:2}
|
1
2
3
4
5
6
7
|
type CompositeLit struct {
Type Expr // literal type; or nil
Lbrace token.Pos // position of "{"
Elts []Expr // list of composite elements; or nil
Rbrace token.Pos // position of "}"
Incomplete bool // true if (source) expressions are missing in the Elts list
}
|
ast.CompositeLit.Type
对应复合类型的表达式,ast.CompositeLit.Elts
是复合类型初始元素列表。
8.3.1 数组和切片面值ArrayType
Type为ArrayType的CompositeLit
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`[...]int{1,2:3}`)
ast.Print(nil, expr)
}
|
复合面值语法树由ast.CompositeLit结构体表示,其中ast.CompositeLit.Type成员为ast.ArrayType表示这是数组或切片类型(如果没有长度信息则为切片类型,否则就是数组),而ast.CompositeLitElts成员则是元素的值。
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
|
0 *ast.CompositeLit {
1 . Type: *ast.ArrayType {
2 . . Lbrack: 1
3 . . Len: *ast.Ellipsis {
4 . . . Ellipsis: 2
5 . . }
6 . . Elt: *ast.Ident {
7 . . . NamePos: 6
8 . . . Name: "int"
9 . . . Obj: *ast.Object {
10 . . . . Kind: bad
11 . . . . Name: ""
12 . . . }
13 . . }
14 . }
15 . Lbrace: 9
16 . Elts: []ast.Expr (len = 2) {
17 . . 0: *ast.BasicLit {
18 . . . ValuePos: 10
19 . . . Kind: INT
20 . . . Value: "1"
21 . . }
22 . . 1: *ast.KeyValueExpr {
23 . . . Key: *ast.BasicLit {
24 . . . . ValuePos: 12
25 . . . . Kind: INT
26 . . . . Value: "2"
27 . . . }
28 . . . Colon: 13
29 . . . Value: *ast.BasicLit {
30 . . . . ValuePos: 14
31 . . . . Kind: INT
32 . . . . Value: "3"
33 . . . }
34 . . }
35 . }
36 . Rbrace: 15
37 . Incomplete: false
38 }
|
8.3.2 结构体面值StructType
Type为StructType的CompositeLit
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`struct{X int}{X:1}`)
ast.Print(nil, expr)
}
|
结构体面值依然是通过ast.CompositeLit结构体描述。结构体中成员的初始化通过ast.KeyValueExpr结构体初始化,Key部分为X表示成员名字,Value部分为X成员的初始值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
0 *ast.CompositeLit {
1 . Type: *ast.StructType {...}
32 . Lbrace: 14
33 . Elts: []ast.Expr (len = 1) {
34 . . 0: *ast.KeyValueExpr {
35 . . . Key: *ast.Ident {
36 . . . . NamePos: 15
37 . . . . Name: "X"
38 . . . }
39 . . . Colon: 16
40 . . . Value: *ast.BasicLit {
41 . . . . ValuePos: 17
42 . . . . Kind: INT
43 . . . . Value: "1"
44 . . . }
45 . . }
46 . }
47 . Rbrace: 18
48 . Incomplete: false
49 }
|
8.3.3 map面值MapType
Type为MapType的CompositeLit
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`map[int]int{1:2}`)
ast.Print(nil, expr)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
18 . Elts: []ast.Expr (len = 1) {
19 . . 0: *ast.KeyValueExpr {
20 . . . Key: *ast.BasicLit {
21 . . . . ValuePos: 13
22 . . . . Kind: INT
23 . . . . Value: "1"
24 . . . }
25 . . . Colon: 14
26 . . . Value: *ast.BasicLit {
27 . . . . ValuePos: 15
28 . . . . Kind: INT
29 . . . . Value: "2"
30 . . . }
31 . . }
32 . }
|
九、复合表达式
9.1 表达式语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
PrimaryExpr = Operand
| Conversion
| MethodExpr
| PrimaryExpr Selector
| PrimaryExpr Index
| PrimaryExpr Slice
| PrimaryExpr TypeAssertion
| PrimaryExpr Arguments
.
Selector = "." identifier .
Index = "[" Expression "]" .
Slice = "[" [ Expression ] ":" [ Expression ] "]"
| "[" [ Expression ] ":" Expression ":" Expression "]" .
TypeAssertion = "." "(" Type ")" .
Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
|
9.2 转型和函数调用CallExpr
1
2
|
Conversion = Type "(" Expression [ "," ] ")" .
Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
|
转型操作和一个参数的函数相似,但以一个类型开始,例如int(x)
将x转换为int类型
1
2
3
4
|
func main() {
expr, _ := parser.ParseExpr(`int(x)`)
ast.Print(nil, expr)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
0 *ast.CallExpr {
1 . Fun: *ast.Ident {
2 . . NamePos: 1
3 . . Name: "int"
4 . . Obj: *ast.Object {
5 . . . Kind: bad
6 . . . Name: ""
7 . . }
8 . }
9 . Lparen: 4
10 . Args: []ast.Expr (len = 1) {
11 . . 0: *ast.Ident {
12 . . . NamePos: 5
13 . . . Name: "x"
14 . . . Obj: *(obj @ 4)
15 . . }
16 . }
17 . Ellipsis: 0
18 . Rparen: 6
19 }
|
转型和函数调用均使用ast.CallExpr
表示,如果Fun是类型表达式则表示一个转型操作
1
2
3
4
5
6
7
|
type CallExpr struct {
Fun Expr // function expression
Lparen token.Pos // position of "("
Args []Expr // function arguments; or nil
Ellipsis token.Pos // position of "..." (token.NoPos if there is no "...")
Rparen token.Pos // position of ")"
}
|
9.3 点选择运算SelectorExpr
1
2
|
PrimaryExpr = PrimaryExpr Selector .
Selector = "." identifier .
|
如果有表达式x,则可以通过x.y访问其成员或方法函数。如果是x导入包,那么x.y将变成标识符含义。在语法树解析阶段并无法区分一个选择表达式和导入包中的标识符。
x.y
解析的语法树结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
0 *ast.SelectorExpr {
1 . X: *ast.Ident {
2 . . NamePos: 1
3 . . Name: "x"
4 . . Obj: *ast.Object {
5 . . . Kind: bad
6 . . . Name: ""
7 . . }
8 . }
9 . Sel: *ast.Ident {
10 . . NamePos: 3
11 . . Name: "y"
12 . }
13 }
|
使用ast.SelectorExpr
表示点选择运算表达式
1
2
3
4
|
type SelectorExpr struct {
X Expr // expression
Sel *Ident // field selector
}
|
9.4 索引运算IndexExpr
1
2
|
PrimaryExpr = PrimaryExpr Index .
Index = "[" Expression "]" .
|
x[y]
解析的语法树结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
0 *ast.IndexExpr {
1 . X: *ast.Ident {
2 . . NamePos: 1
3 . . Name: "x"
4 . . Obj: *ast.Object {
5 . . . Kind: bad
6 . . . Name: ""
7 . . }
8 . }
9 . Lbrack: 2
10 . Index: *ast.Ident {
11 . . NamePos: 3
12 . . Name: "y"
13 . . Obj: *(obj @ 4)
14 . }
15 . Rbrack: 4
16 }
|
使用ast.IndexExpr
表示索引运算表达式
1
2
3
4
5
6
|
type IndexExpr struct {
X Expr // expression
Lbrack token.Pos // position of "["
Index Expr // index expression
Rbrack token.Pos // position of "]"
}
|
其中X和Index成员都是表达式,具体的语义需要根据上下文判断X表达式的类型才能决定Index索引表达式的类型。
9.5 切片运算SliceExpr
切片运算是在数组或切片基础上生成新的切片,切片运算主要包含开始索引、结束索引和最大范围三个部分。
1
2
3
4
|
PrimaryExpr = PrimaryExpr Slice
Slice = "[" [ Expression ] ":" [ Expression ] "]"
| "[" [ Expression ] ":" Expression ":" Expression "]"
.
|
x[1:2:3]
切片运算的语法树
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
|
0 *ast.SliceExpr {
1 . X: *ast.Ident {
2 . . NamePos: 1
3 . . Name: "x"
4 . . Obj: *ast.Object {
5 . . . Kind: bad
6 . . . Name: ""
7 . . }
8 . }
9 . Lbrack: 2
10 . Low: *ast.BasicLit {
11 . . ValuePos: 3
12 . . Kind: INT
13 . . Value: "1"
14 . }
15 . High: *ast.BasicLit {
16 . . ValuePos: 5
17 . . Kind: INT
18 . . Value: "2"
19 . }
20 . Max: *ast.BasicLit {
21 . . ValuePos: 7
22 . . Kind: INT
23 . . Value: "3"
24 . }
25 . Slice3: true
26 . Rbrack: 8
27 }
|
1
2
3
4
5
6
7
8
9
|
type SliceExpr struct {
X Expr // expression
Lbrack token.Pos // position of "["
Low Expr // begin of slice range; or nil
High Expr // end of slice range; or nil
Max Expr // maximum capacity of slice; or nil
Slice3 bool // true if 3-index slice (2 colons present)
Rbrack token.Pos // position of "]"
}
|
其中X、Low、High、Max分别表示切片运算的主体、开始索引、结束索引和最大范围。
9.6 类型断言TypeAssertExpr
类型断言是判断一个接口对象是否满足另一个接口、或者接口持有的对象是否是一个确定的非接口类型。
1
2
|
PrimaryExpr = PrimaryExpr TypeAssertion .
TypeAssertion = "." "(" Type ")" .
|
x.(y)
就是将x接口断言为y接口或y类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
0 *ast.TypeAssertExpr {
1 . X: *ast.Ident {
2 . . NamePos: 1
3 . . Name: "x"
4 . . Obj: *ast.Object {
5 . . . Kind: bad
6 . . . Name: ""
7 . . }
8 . }
9 . Lparen: 3
10 . Type: *ast.Ident {
11 . . NamePos: 4
12 . . Name: "y"
13 . . Obj: *(obj @ 4)
14 . }
15 . Rparen: 5
16 }
|
使用ast.TypeAssertExpr
表示断言运算表达式
1
2
3
4
5
6
|
type TypeAssertExpr struct {
X Expr // expression
Lparen token.Pos // position of "("
Type Expr // asserted type; nil means type switch X.(type)
Rparen token.Pos // position of ")"
}
|
十、语句块和语句
10.1 语句规范
1
2
3
4
5
6
7
8
9
10
|
FunctionBody = Block .
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
Statement = Declaration | LabeledStmt | SimpleStmt
| GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt
| FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt
| DeferStmt
.
|
- FunctionBody函数体对应一个Block语句块。每个Block语句块内部由多个语句列表StatementList组成,每个语句之间通过分号分割。
- 语句又分为声明语句、标签语句、普通表达式语句和其他诸多控制流语句。
10.2 空语句块Stmt
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, parser.AllErrors)
if err != nil {
log.Fatal(err)
return
}
ast.Print(nil, f.Decls[0].(*ast.FuncDecl).Body)
}
const src = `package pkgname
func main() {}
`
|
1
2
3
4
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . Rbrace: 30
3 }
|
函数的声明由ast.FuncDecl结构体定义,其中的Body成员是ast.BlockStmt类型。ast.BlockStmt类型的定义如下:
1
2
3
4
5
6
7
8
9
|
type Stmt interface {
Node
// contains filtered or unexported methods
}
type BlockStmt struct {
Lbrace token.Pos // position of "{"
List []Stmt
Rbrace token.Pos // position of "}"
}
|
10.3 表达式语句ExprStmt
1
|
ExpressionStmt = Expression .
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
chai-mba:02 chai$ go run main.go
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.ExprStmt {
4 . . . X: *ast.BasicLit {
5 . . . . ValuePos: 32
6 . . . . Kind: INT
7 . . . . Value: "42"
8 . . . }
9 . . }
10 . }
11 . Rbrace: 35
12 }
|
使用ExprStmt表示表达式语句
1
2
3
|
type ExprStmt struct {
X Expr // expression
}
|
10.4 返回语句ReturnStmt
1
2
|
ReturnStmt = "return" [ ExpressionList ] .
ExpressionList = Expression { "," Expression } .
|
1
2
3
|
func main() {
return 42, err
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.ReturnStmt {
4 . . . Return: 32
5 . . . Results: []ast.Expr (len = 2) {
6 . . . . 0: *ast.BasicLit {
7 . . . . . ValuePos: 39
8 . . . . . Kind: INT
9 . . . . . Value: "42"
10 . . . . }
11 . . . . 1: *ast.Ident {
12 . . . . . NamePos: 43
13 . . . . . Name: "err"
14 . . . . }
15 . . . }
16 . . }
17 . }
18 . Rbrace: 47
19 }
|
使用ast.ReturnStmt
表示返回语句表达式
1
2
3
4
|
type ReturnStmt struct {
Return token.Pos // position of "return" keyword
Results []Expr // result expressions; or nil
}
|
其中Return成员表示return关键字的位置,Results成员对应一个表达式列表,如果为nil表示没有返回值。
10.5 声明语句DeclStmt
1
2
|
Declaration = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
|
1
2
3
|
func main() {
var a int
}
|
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
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.DeclStmt {
4 . . . Decl: *ast.GenDecl {
5 . . . . TokPos: 32
6 . . . . Tok: var
7 . . . . Lparen: 0
8 . . . . Specs: []ast.Spec (len = 1) {
9 . . . . . 0: *ast.ValueSpec {
10 . . . . . . Names: []*ast.Ident (len = 1) {
11 . . . . . . . 0: *ast.Ident {
12 . . . . . . . . NamePos: 36
13 . . . . . . . . Name: "a"
14 . . . . . . . . Obj: *ast.Object {...}
20 . . . . . . . }
21 . . . . . . }
22 . . . . . . Type: *ast.Ident {
23 . . . . . . . NamePos: 38
24 . . . . . . . Name: "int"
25 . . . . . . }
26 . . . . . }
27 . . . . }
28 . . . . Rparen: 0
29 . . . }
30 . . }
31 . }
32 . Rbrace: 42
33 }
|
使用ast.DeclStmt
表示声明语句表达式
1
2
3
|
type DeclStmt struct {
Decl Decl // *GenDecl with CONST, TYPE, or VAR token
}
|
10.6 短声明和多赋值语句AssignStmt
短声明语法和多赋值语句类似,它是在声明变量的同时进行多赋值初始化,变量类型从赋值表达式自动推导。
1
2
|
Assignment = ExpressionList assign_op ExpressionList .
ShortVarDecl = IdentifierList ":=" ExpressionList .
|
1
2
3
|
func main() {
a, b := 1, 2
}
|
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
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.AssignStmt {
4 . . . Lhs: []ast.Expr (len = 2) {
5 . . . . 0: *ast.Ident {
6 . . . . . NamePos: 32
7 . . . . . Name: "a"
8 . . . . . Obj: *ast.Object {
9 . . . . . . Kind: var
10 . . . . . . Name: "a"
11 . . . . . . Decl: *(obj @ 3)
12 . . . . . }
13 . . . . }
14 . . . . 1: *ast.Ident {
15 . . . . . NamePos: 35
16 . . . . . Name: "b"
17 . . . . . Obj: *ast.Object {
18 . . . . . . Kind: var
19 . . . . . . Name: "b"
20 . . . . . . Decl: *(obj @ 3)
21 . . . . . }
22 . . . . }
23 . . . }
24 . . . TokPos: 37
25 . . . Tok: :=
26 . . . Rhs: []ast.Expr (len = 2) {
27 . . . . 0: *ast.BasicLit {
28 . . . . . ValuePos: 40
29 . . . . . Kind: INT
30 . . . . . Value: "1"
31 . . . . }
32 . . . . 1: *ast.BasicLit {
33 . . . . . ValuePos: 43
34 . . . . . Kind: INT
35 . . . . . Value: "2"
36 . . . . }
37 . . . }
38 . . }
39 . }
40 . Rbrace: 45
41 }
|
使用ast.AssignStmt
表示短声明和多赋值语句表达式
1
2
3
4
5
6
|
type AssignStmt struct {
Lhs []Expr
TokPos token.Pos // position of Tok
Tok token.Token // assignment token, DEFINE
Rhs []Expr
}
|
Lhs表示左边的表达式或标识符列表,而Rhs表示右边的表达式列表。短声明和多赋值语句是通过Tok来进行区分。
10.7 if/else分支语句IfStmt
1
|
IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
|
1
2
3
|
func main() {
if true {} else {}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.IfStmt {
4 . . . If: 32
5 . . . Cond: *ast.Ident {
6 . . . . NamePos: 35
7 . . . . Name: "true"
8 . . . }
9 . . . Body: *ast.BlockStmt {
10 . . . . Lbrace: 40
11 . . . . Rbrace: 41
12 . . . }
13 . . . Else: *ast.BlockStmt {
14 . . . . Lbrace: 48
15 . . . . Rbrace: 49
16 . . . }
17 . . }
18 . }
19 . Rbrace: 51
20 }
|
使用ast.IfStmt
表示if/else语句表达式
1
2
3
4
5
6
7
|
type IfStmt struct {
If token.Pos // position of "if" keyword
Init Stmt // initialization statement; or nil
Cond Expr // condition
Body *BlockStmt
Else Stmt // else branch; or nil
}
|
其中的Cond为分支的条件表达式,Body为分支的主体语句块,Else为补充的语句块。
10.8 for循环ForStmt
1
2
3
4
5
6
7
8
9
|
ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
Condition = Expression .
ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
InitStmt = SimpleStmt .
PostStmt = SimpleStmt .
RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
|
四种支持的语法规范
1
2
3
4
|
for {}
for true {}
for i := 0; true; i++ {}
for i, v := range m {}
|
1
2
3
|
func main() {
for x; y; z {}
}
|
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
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.ForStmt {
4 . . . For: 32
5 . . . Init: *ast.ExprStmt {
6 . . . . X: *ast.Ident {
7 . . . . . NamePos: 36
8 . . . . . Name: "x"
9 . . . . }
10 . . . }
11 . . . Cond: *ast.Ident {
12 . . . . NamePos: 39
13 . . . . Name: "y"
14 . . . }
15 . . . Post: *ast.ExprStmt {
16 . . . . X: *ast.Ident {
17 . . . . . NamePos: 42
18 . . . . . Name: "z"
19 . . . . }
20 . . . }
21 . . . Body: *ast.BlockStmt {
22 . . . . Lbrace: 44
23 . . . . Rbrace: 45
24 . . . }
25 . . }
26 . }
27 . Rbrace: 47
28 }
|
使用ast.ForStmt
表示for-condition循环表达式
1
2
3
4
5
6
7
|
type ForStmt struct {
For token.Pos // position of "for" keyword
Init Stmt // initialization statement; or nil
Cond Expr // condition; or nil
Post Stmt // post iteration statement; or nil
Body *BlockStmt
}
|
其中条件部分必须是表达式,初始化和迭代部分可以是普通的语句(普通语句是短声明和多赋值等,不能包含分支等复杂语句)
1
2
3
|
func main() {
for range ch {}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.RangeStmt {
4 . . . For: 32
5 . . . TokPos: 0
6 . . . Tok: ILLEGAL
7 . . . X: *ast.Ident {
8 . . . . NamePos: 42
9 . . . . Name: "ch"
10 . . . }
11 . . . Body: *ast.BlockStmt {
12 . . . . Lbrace: 45
13 . . . . Rbrace: 46
14 . . . }
15 . . }
16 . }
17 . Rbrace: 48
18 }
|
使用ast.RangeStmt
表示for-range循环表达式
1
2
3
4
5
6
7
8
|
type RangeStmt struct {
For token.Pos // position of "for" keyword
Key, Value Expr // Key, Value may be nil
TokPos token.Pos // position of Tok; invalid if Key == nil
Tok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE
X Expr // value to range over
Body *BlockStmt
}
|
其中Key和Value对应循环时的迭代位置和值,X成员是生成要循环对象的表达式(可能是数组、切片、map和管道等),Body表示循环体语句块。
10.9 类型断言TypeAssertExpr
1
2
|
PrimaryExpr = PrimaryExpr TypeAssertion.
TypeAssertion = "." "(" Type ")" .
|
1
2
3
|
func main() {
x.(int)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.ExprStmt {
4 . . . X: *ast.TypeAssertExpr {
5 . . . . X: *ast.Ident {
6 . . . . . NamePos: 32
7 . . . . . Name: "x"
8 . . . . }
9 . . . . Lparen: 34
10 . . . . Type: *ast.Ident {
11 . . . . . NamePos: 35
12 . . . . . Name: "int"
13 . . . . }
14 . . . . Rparen: 38
15 . . . }
16 . . }
17 . }
18 . Rbrace: 40
19 }
|
使用ast.TypeAssertExpr
表示类型断言语句表达式
1
2
3
4
5
6
|
type TypeAssertExpr struct {
X Expr // expression
Lparen token.Pos // position of "("
Type Expr // asserted type; nil means type switch X.(type)
Rparen token.Pos // position of ")"
}
|
其中X成员是类型断言的主体表达式(产生一个接口值),Type成员是类型的表达式。
10.10 go和defer语句GoStmt/DeferStmt
1
2
3
4
5
6
7
8
|
type GoStmt struct {
Go token.Pos // position of "go" keyword
Call *CallExpr
}
type DeferStmt struct {
Defer token.Pos // position of "defer" keyword
Call *CallExpr
}
|
1
2
3
|
func main() {
go hello("光谷码农")
}
|
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
|
0 *ast.BlockStmt {
1 . Lbrace: 29
2 . List: []ast.Stmt (len = 1) {
3 . . 0: *ast.GoStmt {
4 . . . Go: 32
5 . . . Call: *ast.CallExpr {
6 . . . . Fun: *ast.Ident {
7 . . . . . NamePos: 35
8 . . . . . Name: "hello"
9 . . . . }
10 . . . . Lparen: 40
11 . . . . Args: []ast.Expr (len = 1) {
12 . . . . . 0: *ast.BasicLit {
13 . . . . . . ValuePos: 41
14 . . . . . . Kind: STRING
15 . . . . . . Value: "\"光谷码农\""
16 . . . . . }
17 . . . . }
18 . . . . Ellipsis: 0
19 . . . . Rparen: 55
20 . . . }
21 . . }
22 . }
23 . Rbrace: 57
24 }
|