| // 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 |
| 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 (*node) aNode() {} |
| |
| // ---------------------------------------------------------------------------- |
| // Files |
| |
| // package PkgName; DeclList[0], DeclList[1], ... |
| type File struct { |
| Pragma Pragma |
| PkgName *Name |
| DeclList []Decl |
| EOF Pos |
| 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 |
| 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 } |
| |
| 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 *CallExpr |
| 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 |
| } |