// 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 { // Pos() returns the position associated with the node as follows: // 1) The position of a node representing a terminal syntax production // (Name, BasicLit, etc.) is the position of the respective production // in the source. // 2) The position of a node representing a non-terminal production // (IndexExpr, IfStmt, etc.) is the position of a token uniquely // associated with that production; usually the left-most one // ('[' for IndexExpr, 'if' for IfStmt, etc.) Pos() Pos SetPos(Pos) aNode() } type node struct { // commented out for now since not yet used // doc *Comment // nil means no comment(s) attached pos Pos } func (n *node) Pos() Pos { return n.pos } func (n *node) SetPos(pos Pos) { n.pos = pos } func (*node) aNode() {} // ---------------------------------------------------------------------------- // Files // package PkgName; DeclList[0], DeclList[1], ... type File struct { Pragma Pragma PkgName *Name DeclList []Decl EOF Pos GoVersion string node } // ---------------------------------------------------------------------------- // Declarations type ( Decl interface { Node aDecl() } // Path // LocalPkgName Path ImportDecl struct { Group *Group // nil means not part of a group Pragma Pragma LocalPkgName *Name // including "."; nil means no rename present Path *BasicLit // Path.Bad || Path.Kind == StringLit; nil means no path decl } // NameList // NameList = Values // NameList Type = Values ConstDecl struct { Group *Group // nil means not part of a group Pragma Pragma NameList []*Name Type Expr // nil means no type Values Expr // nil means no values decl } // Name Type TypeDecl struct { Group *Group // nil means not part of a group Pragma Pragma Name *Name TParamList []*Field // nil means no type parameters Alias bool Type Expr decl } // NameList Type // NameList Type = Values // NameList = Values VarDecl struct { Group *Group // nil means not part of a group Pragma Pragma NameList []*Name Type Expr // nil means no type Values Expr // nil means no values decl } // func Name Type { Body } // func Name Type // func Receiver Name Type { Body } // func Receiver Name Type FuncDecl struct { Pragma Pragma Recv *Field // nil means regular function Name *Name TParamList []*Field // nil means no type parameters Type *FuncType Body *BlockStmt // nil means no body (forward declaration) decl } ) type decl struct{ node } func (*decl) aDecl() {} // All declarations belonging to the same group point to the same Group node. type Group struct { _ int // not empty so we are guaranteed different Group instances } // ---------------------------------------------------------------------------- // Expressions func NewName(pos Pos, value string) *Name { n := new(Name) n.pos = pos n.Value = value return n } type ( Expr interface { Node typeInfo aExpr() } // Placeholder for an expression that failed to parse // correctly and where we can't provide a better node. BadExpr struct { expr } // Value Name struct { Value string expr } // Value BasicLit struct { Value string Kind LitKind Bad bool // true means the literal Value has syntax errors expr } // Type { ElemList[0], ElemList[1], ... } CompositeLit struct { Type Expr // nil means no literal type ElemList []Expr NKeys int // number of elements with keys Rbrace Pos expr } // Key: Value KeyValueExpr struct { Key, Value Expr expr } // func Type { Body } FuncLit struct { Type *FuncType Body *BlockStmt expr } // (X) ParenExpr struct { X Expr expr } // X.Sel SelectorExpr struct { X Expr Sel *Name expr } // X[Index] // X[T1, T2, ...] (with Ti = Index.(*ListExpr).ElemList[i]) 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 Type Expr expr } // X.(type) // Lhs := X.(type) TypeSwitchGuard struct { Lhs *Name // nil means no Lhs := X Expr // X.(type) 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 // nil means no arguments 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 element (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, Value Expr expr } // chan Elem // <-chan Elem // chan<- Elem ChanType struct { Dir ChanDir // 0 means no direction Elem Expr expr } ) type expr struct { node typeAndValue // After typechecking, contains the results of typechecking this expression. } 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 { List []Stmt Rbrace Pos 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 == nil means Lhs++ (Op == Add) or Lhs-- (Op == Sub) simpleStmt } BranchStmt struct { Tok token // Break, Continue, Fallthrough, or Goto Label *Name // Target is the continuation of the control flow after executing // the branch; it is computed by the parser if CheckBranches is set. // Target is a *LabeledStmt for gotos, and a *SwitchStmt, *SelectStmt, // or *ForStmt for breaks and continues, depending on the context of // the branch. Target is not set for fallthroughs. Target Stmt stmt } CallStmt struct { Tok token // Go or Defer Call Expr DeferAt Expr // argument to runtime.deferprocat stmt } ReturnStmt struct { Results Expr // nil means no explicit return values stmt } IfStmt struct { Init SimpleStmt Cond Expr Then *BlockStmt Else Stmt // either nil, *IfStmt, or *BlockStmt stmt } ForStmt struct { Init SimpleStmt // incl. *RangeClause Cond Expr Post SimpleStmt Body *BlockStmt stmt } SwitchStmt struct { Init SimpleStmt Tag Expr // incl. *TypeSwitchGuard Body []*CaseClause Rbrace Pos stmt } SelectStmt struct { Body []*CommClause Rbrace Pos stmt } ) type ( RangeClause struct { Lhs Expr // nil means no Lhs = or Lhs := Def bool // means := X Expr // range X simpleStmt } CaseClause struct { Cases Expr // nil means default clause Body []Stmt Colon Pos node } CommClause struct { Comm SimpleStmt // send or receive stmt; nil means default clause Body []Stmt Colon Pos 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 }