diff options
Diffstat (limited to 'src/pkg/go/ast/ast.go')
-rw-r--r-- | src/pkg/go/ast/ast.go | 772 |
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 +} |