| // 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 | |
| } | |