blob: 9555a4b9a8dde6c5c08e543735ee8e9fe81008c1 [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syntax
// ----------------------------------------------------------------------------
// Nodes
type Node interface {
Line() uint32
aNode()
init(p *parser)
}
type node struct {
doc *Comment // nil means no comment(s) attached
pos uint32
line uint32
}
func (*node) aNode() {}
func (n *node) Line() uint32 {
return n.line
}
// TODO(gri) clean up init/initFrom once we have a good file pos story
func (n *node) init(p *parser) {
n.pos = uint32(p.pos)
n.line = uint32(p.line)
}
func (n *node) initFrom(a *node) {
n.pos = a.pos
n.line = a.line
}
// ----------------------------------------------------------------------------
// Files
// package PkgName; DeclList[0], DeclList[1], ...
type File struct {
PkgName *Name
DeclList []Decl
Lines int
node
}
// ----------------------------------------------------------------------------
// Declarations
type (
Decl interface {
Node
aDecl()
}
// Path
// LocalPkgName Path
ImportDecl struct {
LocalPkgName *Name // including "."; nil means no rename present
Path *BasicLit
Group *Group // nil means not part of a group
decl
}
// Name => Orig
AliasDecl struct {
Tok token // Const, Type, Var, or Func
Name *Name
Orig Expr
Group *Group // nil means not part of a group
decl
}
// NameList
// NameList = Values
// NameList Type = Values
ConstDecl struct {
NameList []*Name
Type Expr // nil means no type
Values Expr // nil means no values
Group *Group // nil means not part of a group
decl
}
// Name Type
TypeDecl struct {
Name *Name
Type Expr
Alias bool
Group *Group // nil means not part of a group
decl
}
// NameList Type
// NameList Type = Values
// NameList = Values
VarDecl struct {
NameList []*Name
Type Expr // nil means no type
Values Expr // nil means no values
Group *Group // nil means not part of a group
decl
}
// func Name Type { Body }
// func Name Type
// func Receiver Name Type { Body }
// func Receiver Name Type
FuncDecl struct {
Attr map[string]bool // go:attr map
Recv *Field // nil means regular function
Name *Name
Type *FuncType
Body []Stmt // nil means no body (forward declaration)
Pragma Pragma // TODO(mdempsky): Cleaner solution.
EndLine uint32 // TODO(mdempsky): Cleaner solution.
decl
}
)
type decl struct{ node }
func (*decl) aDecl() {}
// All declarations belonging to the same group point to the same Group node.
type Group struct {
dummy int // not empty so we are guaranteed different Group instances
}
// ----------------------------------------------------------------------------
// Expressions
type (
Expr interface {
Node
aExpr()
}
// Value
Name struct {
Value string
expr
}
// Value
BasicLit struct {
Value string
Kind LitKind
expr
}
// Type { ElemList[0], ElemList[1], ... }
CompositeLit struct {
Type Expr // nil means no literal type
ElemList []Expr
NKeys int // number of elements with keys
EndLine uint32 // TODO(mdempsky): Cleaner solution.
expr
}
// Key: Value
KeyValueExpr struct {
Key, Value Expr
expr
}
// func Type { Body }
FuncLit struct {
Type *FuncType
Body []Stmt
EndLine uint32 // TODO(mdempsky): Cleaner solution.
expr
}
// (X)
ParenExpr struct {
X Expr
expr
}
// X.Sel
SelectorExpr struct {
X Expr
Sel *Name
expr
}
// X[Index]
IndexExpr struct {
X Expr
Index Expr
expr
}
// X[Index[0] : Index[1] : Index[2]]
SliceExpr struct {
X Expr
Index [3]Expr
// Full indicates whether this is a simple or full slice expression.
// In a valid AST, this is equivalent to Index[2] != nil.
// TODO(mdempsky): This is only needed to report the "3-index
// slice of string" error when Index[2] is missing.
Full bool
expr
}
// X.(Type)
AssertExpr struct {
X Expr
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
Type Expr
expr
}
Operation struct {
Op Operator
X, Y Expr // Y == nil means unary expression
expr
}
// Fun(ArgList[0], ArgList[1], ...)
CallExpr struct {
Fun Expr
ArgList []Expr
HasDots bool // last argument is followed by ...
expr
}
// ElemList[0], ElemList[1], ...
ListExpr struct {
ElemList []Expr
expr
}
// [Len]Elem
ArrayType struct {
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
Len Expr // nil means Len is ...
Elem Expr
expr
}
// []Elem
SliceType struct {
Elem Expr
expr
}
// ...Elem
DotsType struct {
Elem Expr
expr
}
// struct { FieldList[0] TagList[0]; FieldList[1] TagList[1]; ... }
StructType struct {
FieldList []*Field
TagList []*BasicLit // i >= len(TagList) || TagList[i] == nil means no tag for field i
expr
}
// Name Type
// Type
Field struct {
Name *Name // nil means anonymous field/parameter (structs/parameters), or embedded interface (interfaces)
Type Expr // field names declared in a list share the same Type (identical pointers)
node
}
// interface { MethodList[0]; MethodList[1]; ... }
InterfaceType struct {
MethodList []*Field
expr
}
FuncType struct {
ParamList []*Field
ResultList []*Field
expr
}
// map[Key]Value
MapType struct {
Key Expr
Value Expr
expr
}
// chan Elem
// <-chan Elem
// chan<- Elem
ChanType struct {
Dir ChanDir // 0 means no direction
Elem Expr
expr
}
)
type expr struct{ node }
func (*expr) aExpr() {}
type ChanDir uint
const (
_ ChanDir = iota
SendOnly
RecvOnly
)
// ----------------------------------------------------------------------------
// Statements
type (
Stmt interface {
Node
aStmt()
}
SimpleStmt interface {
Stmt
aSimpleStmt()
}
EmptyStmt struct {
simpleStmt
}
LabeledStmt struct {
Label *Name
Stmt Stmt
stmt
}
BlockStmt struct {
Body []Stmt
stmt
}
ExprStmt struct {
X Expr
simpleStmt
}
SendStmt struct {
Chan, Value Expr // Chan <- Value
simpleStmt
}
DeclStmt struct {
DeclList []Decl
stmt
}
AssignStmt struct {
Op Operator // 0 means no operation
Lhs, Rhs Expr // Rhs == ImplicitOne means Lhs++ (Op == Add) or Lhs-- (Op == Sub)
simpleStmt
}
BranchStmt struct {
Tok token // Break, Continue, Fallthrough, or Goto
Label *Name
stmt
}
CallStmt struct {
Tok token // Go or Defer
Call *CallExpr
stmt
}
ReturnStmt struct {
Results Expr // nil means no explicit return values
stmt
}
IfStmt struct {
Init SimpleStmt
Cond Expr
Then []Stmt
Else Stmt // either *IfStmt or *BlockStmt
stmt
}
ForStmt struct {
Init SimpleStmt // incl. *RangeClause
Cond Expr
Post SimpleStmt
Body []Stmt
stmt
}
SwitchStmt struct {
Init SimpleStmt
Tag Expr
Body []*CaseClause
stmt
}
SelectStmt struct {
Body []*CommClause
stmt
}
)
type (
RangeClause struct {
Lhs Expr // nil means no Lhs = or Lhs :=
Def bool // means :=
X Expr // range X
simpleStmt
}
TypeSwitchGuard struct {
// TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments)
Lhs *Name // nil means no Lhs :=
X Expr // X.(type)
expr
}
CaseClause struct {
Cases Expr // nil means default clause
Body []Stmt
node
}
CommClause struct {
Comm SimpleStmt // send or receive stmt; nil means default clause
Body []Stmt
node
}
)
type stmt struct{ node }
func (stmt) aStmt() {}
type simpleStmt struct {
stmt
}
func (simpleStmt) aSimpleStmt() {}
// ----------------------------------------------------------------------------
// Comments
// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
// Kind = Above doesn't make much sense.
type CommentKind uint
const (
Above CommentKind = iota
Below
Left
Right
)
type Comment struct {
Kind CommentKind
Text string
Next *Comment
}