summaryrefslogtreecommitdiff
path: root/src/pkg/go/ast/ast.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/ast/ast.go')
-rw-r--r--src/pkg/go/ast/ast.go772
1 files changed, 772 insertions, 0 deletions
diff --git a/src/pkg/go/ast/ast.go b/src/pkg/go/ast/ast.go
new file mode 100644
index 000000000..6cac8ea1a
--- /dev/null
+++ b/src/pkg/go/ast/ast.go
@@ -0,0 +1,772 @@
+// 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 source files.
+//
+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.
+
+// TODO: For comment positioning only the byte position and not
+// a complete token.Position field is needed. May be able to trim
+// node sizes a bit.
+
+
+type (
+ ExprVisitor interface;
+ StmtVisitor interface;
+ DeclVisitor interface;
+)
+
+
+// All expression nodes implement the Expr interface.
+type Expr interface {
+ // For a (dynamic) node type X, calling Visit with an expression
+ // visitor v invokes the node-specific DoX function of the visitor.
+ //
+ Visit(v ExprVisitor);
+
+ // Pos returns the (beginning) position of the expression.
+ Pos() token.Position;
+}
+
+
+// All statement nodes implement the Stmt interface.
+type Stmt interface {
+ // For a (dynamic) node type X, calling Visit with a statement
+ // visitor v invokes the node-specific DoX function of the visitor.
+ //
+ Visit(v StmtVisitor);
+
+ // Pos returns the (beginning) position of the statement.
+ Pos() token.Position;
+}
+
+
+// All declaration nodes implement the Decl interface.
+type Decl interface {
+ // For a (dynamic) node type X, calling Visit with a declaration
+ // visitor v invokes the node-specific DoX function of the visitor.
+ //
+ Visit(v DeclVisitor);
+
+ // Pos returns the (beginning) position of the declaration.
+ Pos() token.Position;
+}
+
+
+// ----------------------------------------------------------------------------
+// Comments
+
+// A Comment node represents a single //-style or /*-style comment.
+type Comment struct {
+ token.Position; // beginning position of the comment
+ Text []byte; // the comment text (without '\n' for //-style comments)
+ EndLine int; // the line where the comment ends
+}
+
+
+// A Comments node represents a sequence of single comments
+// with no other tokens and no empty lines between.
+//
+type Comments []*Comment
+
+
+// ----------------------------------------------------------------------------
+// Expressions and types
+
+// Support types.
+type (
+ Ident struct;
+ StringLit struct;
+ FuncType struct;
+ BlockStmt struct;
+
+ // A Field represents a Field declaration list in a struct type,
+ // a method in an interface type, or a parameter/result declaration
+ // in a signature.
+ Field struct {
+ Doc Comments; // associated documentation; or nil
+ Names []*Ident; // field/method/parameter names; nil if anonymous field
+ Type Expr; // field/method/parameter type
+ Tag []*StringLit; // field tag; nil if no tag
+ };
+)
+
+
+// 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 "..."
+ };
+
+ // An IntLit node represents an integer literal.
+ IntLit struct {
+ token.Position; // int literal position
+ Value []byte; // literal string; e.g. 42 or 0x7f
+ };
+
+ // A FloatLit node represents a floating-point literal.
+ FloatLit struct {
+ token.Position; // float literal position
+ Value []byte; // literal string; e.g. 3.14 or 1e-9
+ };
+
+ // A CharLit node represents a character literal.
+ CharLit struct {
+ token.Position; // char literal position
+ Value []byte; // literal string, including quotes; e.g. 'a' or '\x7f'
+ };
+
+ // A StringLit node represents a string literal.
+ StringLit struct {
+ token.Position; // string literal position
+ Value []byte; // literal string, including quotes; e.g. "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 StringLit
+ // node; StringList nodes are used only if there are two or more string
+ // literals in a sequence.
+ //
+ StringList struct {
+ Strings []*StringLit; // 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 or slice.
+ IndexExpr struct {
+ X Expr; // expression
+ Index Expr; // index expression or 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
+ };
+
+ // 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; nil if forward declaration
+ Rbrace token.Position; // position of "}"
+ };
+
+ // 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; nil if forward declaration
+ Rbrace token.Position; // position of "}"
+ };
+
+ // 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 *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(); }
+
+
+// All expression/type nodes implement a Visit method which takes
+// an ExprVisitor as argument. For a given node x of type X, and
+// an implementation v of an ExprVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
+type ExprVisitor interface {
+ // Expressions
+ DoBadExpr(x *BadExpr);
+ DoIdent(x *Ident);
+ DoIntLit(x *IntLit);
+ DoFloatLit(x *FloatLit);
+ DoCharLit(x *CharLit);
+ DoStringLit(x *StringLit);
+ DoStringList(x *StringList);
+ DoFuncLit(x *FuncLit);
+ DoCompositeLit(x *CompositeLit);
+ DoParenExpr(x *ParenExpr);
+ DoSelectorExpr(x *SelectorExpr);
+ DoIndexExpr(x *IndexExpr);
+ DoTypeAssertExpr(x *TypeAssertExpr);
+ DoCallExpr(x *CallExpr);
+ DoStarExpr(x *StarExpr);
+ DoUnaryExpr(x *UnaryExpr);
+ DoBinaryExpr(x *BinaryExpr);
+ DoKeyValueExpr(x *KeyValueExpr);
+
+ // Type expressions
+ DoEllipsis(x *Ellipsis);
+ DoArrayType(x *ArrayType);
+ DoStructType(x *StructType);
+ DoFuncType(x *FuncType);
+ DoInterfaceType(x *InterfaceType);
+ DoMapType(x *MapType);
+ DoChanType(x *ChanType);
+}
+
+
+// Visit() implementations for all expression/type nodes.
+//
+func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); }
+func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); }
+func (x *Ellipsis) Visit(v ExprVisitor) { v.DoEllipsis(x); }
+func (x *IntLit) Visit(v ExprVisitor) { v.DoIntLit(x); }
+func (x *FloatLit) Visit(v ExprVisitor) { v.DoFloatLit(x); }
+func (x *CharLit) Visit(v ExprVisitor) { v.DoCharLit(x); }
+func (x *StringLit) Visit(v ExprVisitor) { v.DoStringLit(x); }
+func (x *StringList) Visit(v ExprVisitor) { v.DoStringList(x); }
+func (x *FuncLit) Visit(v ExprVisitor) { v.DoFuncLit(x); }
+func (x *CompositeLit) Visit(v ExprVisitor) { v.DoCompositeLit(x); }
+func (x *ParenExpr) Visit(v ExprVisitor) { v.DoParenExpr(x); }
+func (x *SelectorExpr) Visit(v ExprVisitor) { v.DoSelectorExpr(x); }
+func (x *IndexExpr) Visit(v ExprVisitor) { v.DoIndexExpr(x); }
+func (x *TypeAssertExpr) Visit(v ExprVisitor) { v.DoTypeAssertExpr(x); }
+func (x *CallExpr) Visit(v ExprVisitor) { v.DoCallExpr(x); }
+func (x *StarExpr) Visit(v ExprVisitor) { v.DoStarExpr(x); }
+func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); }
+func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); }
+func (x *KeyValueExpr) Visit(v ExprVisitor) { v.DoKeyValueExpr(x); }
+
+func (x *ArrayType) Visit(v ExprVisitor) { v.DoArrayType(x); }
+func (x *StructType) Visit(v ExprVisitor) { v.DoStructType(x); }
+func (x *FuncType) Visit(v ExprVisitor) { v.DoFuncType(x); }
+func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); }
+func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); }
+func (x *ChanType) Visit(v ExprVisitor) { v.DoChanType(x); }
+
+
+// IsExported returns whether name is an exported Go symbol
+// (i.e., whether it begins with an uppercase letter).
+func IsExported(name string) bool {
+ ch, len := 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 *ast.Ident) IsExported() bool {
+ return IsExported(name.Value);
+}
+
+func (name *ast.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
+ Type 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(); }
+
+
+// All statement nodes implement a Visit method which takes
+// a StmtVisitor as argument. For a given node x of type X, and
+// an implementation v of a StmtVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
+type StmtVisitor interface {
+ DoBadStmt(s *BadStmt);
+ DoDeclStmt(s *DeclStmt);
+ DoEmptyStmt(s *EmptyStmt);
+ DoLabeledStmt(s *LabeledStmt);
+ DoExprStmt(s *ExprStmt);
+ DoIncDecStmt(s *IncDecStmt);
+ DoAssignStmt(s *AssignStmt);
+ DoGoStmt(s *GoStmt);
+ DoDeferStmt(s *DeferStmt);
+ DoReturnStmt(s *ReturnStmt);
+ DoBranchStmt(s *BranchStmt);
+ DoBlockStmt(s *BlockStmt);
+ DoIfStmt(s *IfStmt);
+ DoCaseClause(s *CaseClause);
+ DoSwitchStmt(s *SwitchStmt);
+ DoTypeCaseClause(s *TypeCaseClause);
+ DoTypeSwitchStmt(s *TypeSwitchStmt);
+ DoCommClause(s *CommClause);
+ DoSelectStmt(s *SelectStmt);
+ DoForStmt(s *ForStmt);
+ DoRangeStmt(s *RangeStmt);
+}
+
+
+// Visit() implementations for all statement nodes.
+//
+func (s *BadStmt) Visit(v StmtVisitor) { v.DoBadStmt(s); }
+func (s *DeclStmt) Visit(v StmtVisitor) { v.DoDeclStmt(s); }
+func (s *EmptyStmt) Visit(v StmtVisitor) { v.DoEmptyStmt(s); }
+func (s *LabeledStmt) Visit(v StmtVisitor) { v.DoLabeledStmt(s); }
+func (s *ExprStmt) Visit(v StmtVisitor) { v.DoExprStmt(s); }
+func (s *IncDecStmt) Visit(v StmtVisitor) { v.DoIncDecStmt(s); }
+func (s *AssignStmt) Visit(v StmtVisitor) { v.DoAssignStmt(s); }
+func (s *GoStmt) Visit(v StmtVisitor) { v.DoGoStmt(s); }
+func (s *DeferStmt) Visit(v StmtVisitor) { v.DoDeferStmt(s); }
+func (s *ReturnStmt) Visit(v StmtVisitor) { v.DoReturnStmt(s); }
+func (s *BranchStmt) Visit(v StmtVisitor) { v.DoBranchStmt(s); }
+func (s *BlockStmt) Visit(v StmtVisitor) { v.DoBlockStmt(s); }
+func (s *IfStmt) Visit(v StmtVisitor) { v.DoIfStmt(s); }
+func (s *CaseClause) Visit(v StmtVisitor) { v.DoCaseClause(s); }
+func (s *SwitchStmt) Visit(v StmtVisitor) { v.DoSwitchStmt(s); }
+func (s *TypeCaseClause) Visit(v StmtVisitor) { v.DoTypeCaseClause(s); }
+func (s *TypeSwitchStmt) Visit(v StmtVisitor) { v.DoTypeSwitchStmt(s); }
+func (s *CommClause) Visit(v StmtVisitor) { v.DoCommClause(s); }
+func (s *SelectStmt) Visit(v StmtVisitor) { v.DoSelectStmt(s); }
+func (s *ForStmt) Visit(v StmtVisitor) { v.DoForStmt(s); }
+func (s *RangeStmt) Visit(v StmtVisitor) { v.DoRangeStmt(s); }
+
+
+// ----------------------------------------------------------------------------
+// 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 {};
+
+ // An ImportSpec node represents a single package import.
+ ImportSpec struct {
+ Doc Comments; // associated documentation; or nil
+ Name *Ident; // local package name (including "."); or nil
+ Path []*StringLit; // package path
+ };
+
+ // A ValueSpec node represents a constant or variable declaration
+ // (ConstSpec or VarSpec production).
+ ValueSpec struct {
+ Doc Comments; // associated documentation; or nil
+ Names []*Ident;
+ Type Expr; // value type; or nil
+ Values []Expr;
+ };
+
+ // A TypeSpec node represents a type declaration (TypeSpec production).
+ TypeSpec struct {
+ Doc Comments; // associated documentation; or nil
+ Name *Ident; // type name
+ Type Expr;
+ };
+)
+
+
+// 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 Comments; // 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 Comments; // 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(); }
+
+
+// All declaration nodes implement a Visit method which takes
+// a DeclVisitor as argument. For a given node x of type X, and
+// an implementation v of a DeclVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
+type DeclVisitor interface {
+ DoBadDecl(d *BadDecl);
+ DoGenDecl(d *GenDecl);
+ DoFuncDecl(d *FuncDecl);
+}
+
+
+// Visit() implementations for all declaration nodes.
+//
+func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); }
+func (d *GenDecl) Visit(v DeclVisitor) { v.DoGenDecl(d); }
+func (d *FuncDecl) Visit(v DeclVisitor) { v.DoFuncDecl(d); }
+
+
+// ----------------------------------------------------------------------------
+// Programs
+
+// A Program node represents the root node of an AST
+// for an entire source file.
+//
+type Program struct {
+ Doc Comments; // associated documentation; or nil
+ token.Position; // position of "package" keyword
+ Name *Ident; // package name
+ Decls []Decl; // top-level declarations
+ Comments []*Comment; // list of unassociated comments
+}