// Copyright 2009 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. // The AST package declares the types used to represent // syntax trees for Go packages. // package ast import ( "go/token"; "unicode"; "utf8"; ) // ---------------------------------------------------------------------------- // Interfaces // // There are 3 main classes of nodes: Expressions and type nodes, // statement nodes, and declaration nodes. The node names usually // match the corresponding Go spec production names to which they // correspond. The node fields correspond to the individual parts // of the respective productions. // // All nodes contain position information marking the beginning of // the corresponding source text segment; it is accessible via the // Pos accessor method. Nodes may contain additional position info // for language constructs where comments may be found between parts // of the construct (typically any larger, parenthesized subpart). // That position information is needed to properly position comments // when printing the construct. // All node types implement the Node interface. type Node interface { // Pos returns the (beginning) position of the node. Pos() token.Position; } // All expression nodes implement the Expr interface. type Expr interface { Node; exprNode(); } // All statement nodes implement the Stmt interface. type Stmt interface { Node; stmtNode(); } // All declaration nodes implement the Decl interface. type Decl interface { Node; declNode(); } // ---------------------------------------------------------------------------- // Comments // A Comment node represents a single //-style or /*-style comment. type Comment struct { token.Position; // beginning position of the comment Text []byte; // comment text (excluding '\n' for //-style comments) } // A CommentGroup represents a sequence of comments // with no other tokens and no empty lines between. // type CommentGroup struct { List []*Comment; Next *CommentGroup; // next comment group in source order } // ---------------------------------------------------------------------------- // Expressions and types // A Field represents a Field declaration list in a struct type, // a method list in an interface type, or a parameter/result declaration // in a signature. // type Field struct { Doc *CommentGroup; // associated documentation; or nil Names []*Ident; // field/method/parameter names; or nil if anonymous field Type Expr; // field/method/parameter type Tag []*BasicLit; // field tag; or nil Comment *CommentGroup; // line comments; or nil } func (f *Field) Pos() token.Position { if len(f.Names) > 0 { return f.Names[0].Pos() } return f.Type.Pos(); } // An expression is represented by a tree consisting of one // or more of the following concrete expression nodes. // type ( // A BadExpr node is a placeholder for expressions containing // syntax errors for which no correct expression nodes can be // created. // BadExpr struct { token.Position; // beginning position of bad expression }; // An Ident node represents an identifier. Ident struct { token.Position; // identifier position Value string; // identifier string (e.g. foobar) }; // An Ellipsis node stands for the "..." type in a // parameter list or the "..." length in an array type. // Ellipsis struct { token.Position; // position of "..." }; // A BasicLit node represents a literal of basic type. BasicLit struct { token.Position; // literal position Kind token.Token; // token.INT, token.FLOAT, token.CHAR, or token.STRING Value []byte; // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 'a', '\x7f', "foo" or `\m\n\o` }; // A StringList node represents a sequence of adjacent string literals. // A single string literal (common case) is represented by a BasicLit // node; StringList nodes are used only if there are two or more string // literals in a sequence. // StringList struct { Strings []*BasicLit; // list of strings, len(Strings) > 1 }; // A FuncLit node represents a function literal. FuncLit struct { Type *FuncType; // function type Body *BlockStmt; // function body }; // A CompositeLit node represents a composite literal. // CompositeLit struct { Type Expr; // literal type Lbrace token.Position; // position of "{" Elts []Expr; // list of composite elements Rbrace token.Position; // position of "}" }; // A ParenExpr node represents a parenthesized expression. ParenExpr struct { token.Position; // position of "(" X Expr; // parenthesized expression Rparen token.Position; // position of ")" }; // A SelectorExpr node represents an expression followed by a selector. SelectorExpr struct { X Expr; // expression Sel *Ident; // field selector }; // An IndexExpr node represents an expression followed by an index. IndexExpr struct { X Expr; // expression Index Expr; // index expression }; // An SliceExpr node represents an expression followed by slice indices. SliceExpr struct { X Expr; // expression Index Expr; // beginning of slice range End Expr; // end of slice range; or nil }; // A TypeAssertExpr node represents an expression followed by a // type assertion. // TypeAssertExpr struct { X Expr; // expression Type Expr; // asserted type; nil means type switch X.(type) }; // A CallExpr node represents an expression followed by an argument list. CallExpr struct { Fun Expr; // function expression Lparen token.Position; // position of "(" Args []Expr; // function arguments Rparen token.Position; // positions of ")" }; // A StarExpr node represents an expression of the form "*" Expression. // Semantically it could be a unary "*" expression, or a pointer type. StarExpr struct { token.Position; // position of "*" X Expr; // operand }; // A UnaryExpr node represents a unary expression. // Unary "*" expressions are represented via StarExpr nodes. // UnaryExpr struct { token.Position; // position of Op Op token.Token; // operator X Expr; // operand }; // A BinaryExpr node represents a binary expression. // BinaryExpr struct { X Expr; // left operand OpPos token.Position; // position of Op Op token.Token; // operator Y Expr; // right operand }; // A KeyValueExpr node represents (key : value) pairs // in composite literals. // KeyValueExpr struct { Key Expr; Colon token.Position; // position of ":" Value Expr; }; ) // The direction of a channel type is indicated by one // of the following constants. // type ChanDir int const ( SEND ChanDir = 1 << iota; RECV; ) // A type is represented by a tree consisting of one // or more of the following type-specific expression // nodes. // type ( // An ArrayType node represents an array or slice type. ArrayType struct { token.Position; // position of "[" Len Expr; // Ellipsis node for [...]T array types, nil for slice types Elt Expr; // element type }; // A StructType node represents a struct type. StructType struct { token.Position; // position of "struct" keyword Lbrace token.Position; // position of "{" Fields []*Field; // list of field declarations Rbrace token.Position; // position of "}" Incomplete bool; // true if (source) fields are missing in the Fields list }; // Pointer types are represented via StarExpr nodes. // A FuncType node represents a function type. FuncType struct { token.Position; // position of "func" keyword Params []*Field; // (incoming) parameters Results []*Field; // (outgoing) results }; // An InterfaceType node represents an interface type. InterfaceType struct { token.Position; // position of "interface" keyword Lbrace token.Position; // position of "{" Methods []*Field; // list of methods Rbrace token.Position; // position of "}" Incomplete bool; // true if (source) methods are missing in the Methods list }; // A MapType node represents a map type. MapType struct { token.Position; // position of "map" keyword Key Expr; Value Expr; }; // A ChanType node represents a channel type. ChanType struct { token.Position; // position of "chan" keyword or "<-" (whichever comes first) Dir ChanDir; // channel direction Value Expr; // value type }; ) // Pos() implementations for expression/type where the position // corresponds to the position of a sub-node. // func (x *StringList) Pos() token.Position { return x.Strings[0].Pos() } func (x *FuncLit) Pos() token.Position { return x.Type.Pos() } func (x *CompositeLit) Pos() token.Position { return x.Type.Pos() } func (x *SelectorExpr) Pos() token.Position { return x.X.Pos() } func (x *IndexExpr) Pos() token.Position { return x.X.Pos() } func (x *SliceExpr) Pos() token.Position { return x.X.Pos() } func (x *TypeAssertExpr) Pos() token.Position { return x.X.Pos() } func (x *CallExpr) Pos() token.Position { return x.Fun.Pos() } func (x *BinaryExpr) Pos() token.Position { return x.X.Pos() } func (x *KeyValueExpr) Pos() token.Position { return x.Key.Pos() } // exprNode() ensures that only expression/type nodes can be // assigned to an ExprNode. func (x *BadExpr) exprNode() {} func (x *Ident) exprNode() {} func (x *Ellipsis) exprNode() {} func (x *BasicLit) exprNode() {} func (x *StringList) exprNode() {} func (x *FuncLit) exprNode() {} func (x *CompositeLit) exprNode() {} func (x *ParenExpr) exprNode() {} func (x *SelectorExpr) exprNode() {} func (x *IndexExpr) exprNode() {} func (x *SliceExpr) exprNode() {} func (x *TypeAssertExpr) exprNode() {} func (x *CallExpr) exprNode() {} func (x *StarExpr) exprNode() {} func (x *UnaryExpr) exprNode() {} func (x *BinaryExpr) exprNode() {} func (x *KeyValueExpr) exprNode() {} func (x *ArrayType) exprNode() {} func (x *StructType) exprNode() {} func (x *FuncType) exprNode() {} func (x *InterfaceType) exprNode() {} func (x *MapType) exprNode() {} func (x *ChanType) exprNode() {} // IsExported returns whether name is an exported Go symbol // (i.e., whether it begins with an uppercase letter). func IsExported(name string) bool { ch, _ := utf8.DecodeRuneInString(name); return unicode.IsUpper(ch); } // IsExported returns whether name is an exported Go symbol // (i.e., whether it begins with an uppercase letter). func (name *Ident) IsExported() bool { return IsExported(name.Value) } func (name *Ident) String() string { return name.Value } // ---------------------------------------------------------------------------- // Statements // A statement is represented by a tree consisting of one // or more of the following concrete statement nodes. // type ( // A BadStmt node is a placeholder for statements containing // syntax errors for which no correct statement nodes can be // created. // BadStmt struct { token.Position; // beginning position of bad statement }; // A DeclStmt node represents a declaration in a statement list. DeclStmt struct { Decl Decl; }; // An EmptyStmt node represents an empty statement. // The "position" of the empty statement is the position // of the immediately preceeding semicolon. // EmptyStmt struct { token.Position; // position of preceeding ";" }; // A LabeledStmt node represents a labeled statement. LabeledStmt struct { Label *Ident; Stmt Stmt; }; // An ExprStmt node represents a (stand-alone) expression // in a statement list. // ExprStmt struct { X Expr; // expression }; // An IncDecStmt node represents an increment or decrement statement. IncDecStmt struct { X Expr; Tok token.Token; // INC or DEC }; // An AssignStmt node represents an assignment or // a short variable declaration. AssignStmt struct { Lhs []Expr; TokPos token.Position; // position of Tok Tok token.Token; // assignment token, DEFINE Rhs []Expr; }; // A GoStmt node represents a go statement. GoStmt struct { token.Position; // position of "go" keyword Call *CallExpr; }; // A DeferStmt node represents a defer statement. DeferStmt struct { token.Position; // position of "defer" keyword Call *CallExpr; }; // A ReturnStmt node represents a return statement. ReturnStmt struct { token.Position; // position of "return" keyword Results []Expr; }; // A BranchStmt node represents a break, continue, goto, // or fallthrough statement. // BranchStmt struct { token.Position; // position of Tok Tok token.Token; // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH) Label *Ident; }; // A BlockStmt node represents a braced statement list. BlockStmt struct { token.Position; // position of "{" List []Stmt; Rbrace token.Position; // position of "}" }; // An IfStmt node represents an if statement. IfStmt struct { token.Position; // position of "if" keyword Init Stmt; Cond Expr; Body *BlockStmt; Else Stmt; }; // A CaseClause represents a case of an expression switch statement. CaseClause struct { token.Position; // position of "case" or "default" keyword Values []Expr; // nil means default case Colon token.Position; // position of ":" Body []Stmt; // statement list; or nil }; // A SwitchStmt node represents an expression switch statement. SwitchStmt struct { token.Position; // position of "switch" keyword Init Stmt; Tag Expr; Body *BlockStmt; // CaseClauses only }; // A TypeCaseClause represents a case of a type switch statement. TypeCaseClause struct { token.Position; // position of "case" or "default" keyword Types []Expr; // nil means default case Colon token.Position; // position of ":" Body []Stmt; // statement list; or nil }; // An TypeSwitchStmt node represents a type switch statement. TypeSwitchStmt struct { token.Position; // position of "switch" keyword Init Stmt; Assign Stmt; // x := y.(type) Body *BlockStmt; // TypeCaseClauses only }; // A CommClause node represents a case of a select statement. CommClause struct { token.Position; // position of "case" or "default" keyword Tok token.Token; // ASSIGN or DEFINE (valid only if Lhs != nil) Lhs, Rhs Expr; // Rhs == nil means default case Colon token.Position; // position of ":" Body []Stmt; // statement list; or nil }; // An SelectStmt node represents a select statement. SelectStmt struct { token.Position; // position of "select" keyword Body *BlockStmt; // CommClauses only }; // A ForStmt represents a for statement. ForStmt struct { token.Position; // position of "for" keyword Init Stmt; Cond Expr; Post Stmt; Body *BlockStmt; }; // A RangeStmt represents a for statement with a range clause. RangeStmt struct { token.Position; // position of "for" keyword Key, Value Expr; // Value may be nil TokPos token.Position; // position of Tok Tok token.Token; // ASSIGN, DEFINE X Expr; // value to range over Body *BlockStmt; }; ) // Pos() implementations for statement nodes where the position // corresponds to the position of a sub-node. // func (s *DeclStmt) Pos() token.Position { return s.Decl.Pos() } func (s *LabeledStmt) Pos() token.Position { return s.Label.Pos() } func (s *ExprStmt) Pos() token.Position { return s.X.Pos() } func (s *IncDecStmt) Pos() token.Position { return s.X.Pos() } func (s *AssignStmt) Pos() token.Position { return s.Lhs[0].Pos() } // stmtNode() ensures that only statement nodes can be // assigned to a StmtNode. // func (s *BadStmt) stmtNode() {} func (s *DeclStmt) stmtNode() {} func (s *EmptyStmt) stmtNode() {} func (s *LabeledStmt) stmtNode() {} func (s *ExprStmt) stmtNode() {} func (s *IncDecStmt) stmtNode() {} func (s *AssignStmt) stmtNode() {} func (s *GoStmt) stmtNode() {} func (s *DeferStmt) stmtNode() {} func (s *ReturnStmt) stmtNode() {} func (s *BranchStmt) stmtNode() {} func (s *BlockStmt) stmtNode() {} func (s *IfStmt) stmtNode() {} func (s *CaseClause) stmtNode() {} func (s *SwitchStmt) stmtNode() {} func (s *TypeCaseClause) stmtNode() {} func (s *TypeSwitchStmt) stmtNode() {} func (s *CommClause) stmtNode() {} func (s *SelectStmt) stmtNode() {} func (s *ForStmt) stmtNode() {} func (s *RangeStmt) stmtNode() {} // ---------------------------------------------------------------------------- // Declarations // A Spec node represents a single (non-parenthesized) import, // constant, type, or variable declaration. // type ( // The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec. Spec interface { Node; specNode(); }; // An ImportSpec node represents a single package import. ImportSpec struct { Doc *CommentGroup; // associated documentation; or nil Name *Ident; // local package name (including "."); or nil Path []*BasicLit; // package path Comment *CommentGroup; // line comments; or nil }; // A ValueSpec node represents a constant or variable declaration // (ConstSpec or VarSpec production). ValueSpec struct { Doc *CommentGroup; // associated documentation; or nil Names []*Ident; // value names Type Expr; // value type; or nil Values []Expr; // initial values; or nil Comment *CommentGroup; // line comments; or nil }; // A TypeSpec node represents a type declaration (TypeSpec production). TypeSpec struct { Doc *CommentGroup; // associated documentation; or nil Name *Ident; // type name Type Expr; Comment *CommentGroup; // line comments; or nil }; ) // Pos() implementations for spec nodes. // func (s *ImportSpec) Pos() token.Position { if s.Name != nil { return s.Name.Pos() } return s.Path[0].Pos(); } func (s *ValueSpec) Pos() token.Position { return s.Names[0].Pos() } func (s *TypeSpec) Pos() token.Position { return s.Name.Pos() } // specNode() ensures that only spec nodes can be // assigned to a Spec. // func (s *ImportSpec) specNode() {} func (s *ValueSpec) specNode() {} func (s *TypeSpec) specNode() {} // A declaration is represented by one of the following declaration nodes. // type ( // A BadDecl node is a placeholder for declarations containing // syntax errors for which no correct declaration nodes can be // created. // BadDecl struct { token.Position; // beginning position of bad declaration }; // A GenDecl node (generic declaration node) represents an import, // constant, type or variable declaration. A valid Lparen position // (Lparen.Line > 0) indicates a parenthesized declaration. // // Relationship between Tok value and Specs element type: // // token.IMPORT *ImportSpec // token.CONST *ValueSpec // token.TYPE *TypeSpec // token.VAR *ValueSpec // GenDecl struct { Doc *CommentGroup; // associated documentation; or nil token.Position; // position of Tok Tok token.Token; // IMPORT, CONST, TYPE, VAR Lparen token.Position; // position of '(', if any Specs []Spec; Rparen token.Position; // position of ')', if any }; // A FuncDecl node represents a function declaration. FuncDecl struct { Doc *CommentGroup; // associated documentation; or nil Recv *Field; // receiver (methods); or nil (functions) Name *Ident; // function/method name Type *FuncType; // position of Func keyword, parameters and results Body *BlockStmt; // function body; or nil (forward declaration) }; ) // The position of a FuncDecl node is the position of its function type. func (d *FuncDecl) Pos() token.Position { return d.Type.Pos() } // declNode() ensures that only declaration nodes can be // assigned to a DeclNode. // func (d *BadDecl) declNode() {} func (d *GenDecl) declNode() {} func (d *FuncDecl) declNode() {} // ---------------------------------------------------------------------------- // Files and packages // A File node represents a Go source file. // type File struct { Doc *CommentGroup; // associated documentation; or nil token.Position; // position of "package" keyword Name *Ident; // package name Decls []Decl; // top-level declarations Comments *CommentGroup; // list of all comments in the source file } // A Package node represents a set of source files // collectively building a Go package. // type Package struct { Name string; // package name Path string; // package path Files map[string]*File; // path-relative filenames }