URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [go/] [ast/] [ast.go] - Rev 747
Compare with Previous | Blame | View Log
// 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.// Package ast declares the types used to represent syntax trees for Go// packages.//package astimport ("go/token""strings""unicode""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() token.Pos // position of first character belonging to the nodeEnd() token.Pos // position of first character immediately after the node}// All expression nodes implement the Expr interface.type Expr interface {NodeexprNode()}// All statement nodes implement the Stmt interface.type Stmt interface {NodestmtNode()}// All declaration nodes implement the Decl interface.type Decl interface {NodedeclNode()}// ----------------------------------------------------------------------------// Comments// A Comment node represents a single //-style or /*-style comment.type Comment struct {Slash token.Pos // position of "/" starting the commentText string // comment text (excluding '\n' for //-style comments)}func (c *Comment) Pos() token.Pos { return c.Slash }func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }// A CommentGroup represents a sequence of comments// with no other tokens and no empty lines between.//type CommentGroup struct {List []*Comment // len(List) > 0}func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }func stripTrailingWhitespace(s string) string {i := len(s)for i > 0 && isWhitespace(s[i-1]) {i--}return s[0:i]}// Text returns the text of the comment,// with the comment markers - //, /*, and */ - removed.func (g *CommentGroup) Text() string {if g == nil {return ""}comments := make([]string, len(g.List))for i, c := range g.List {comments[i] = string(c.Text)}lines := make([]string, 0, 10) // most comments are less than 10 linesfor _, c := range comments {// Remove comment markers.// The parser has given us exactly the comment text.switch c[1] {case '/'://-style commentc = c[2:]// Remove leading space after //, if there is one.// TODO(gri) This appears to be necessary in isolated// cases (bignum.RatFromString) - why?if len(c) > 0 && c[0] == ' ' {c = c[1:]}case '*':/*-style comment */c = c[2 : len(c)-2]}// Split on newlines.cl := strings.Split(c, "\n")// Walk lines, stripping trailing white space and adding to list.for _, l := range cl {lines = append(lines, stripTrailingWhitespace(l))}}// Remove leading blank lines; convert runs of// interior blank lines to a single blank line.n := 0for _, line := range lines {if line != "" || n > 0 && lines[n-1] != "" {lines[n] = linen++}}lines = lines[0:n]// Add final "" entry to get trailing newline from Join.if n > 0 && lines[n-1] != "" {lines = append(lines, "")}return strings.Join(lines, "\n")}// ----------------------------------------------------------------------------// 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 nilNames []*Ident // field/method/parameter names; or nil if anonymous fieldType Expr // field/method/parameter typeTag *BasicLit // field tag; or nilComment *CommentGroup // line comments; or nil}func (f *Field) Pos() token.Pos {if len(f.Names) > 0 {return f.Names[0].Pos()}return f.Type.Pos()}func (f *Field) End() token.Pos {if f.Tag != nil {return f.Tag.End()}return f.Type.End()}// A FieldList represents a list of Fields, enclosed by parentheses or braces.type FieldList struct {Opening token.Pos // position of opening parenthesis/brace, if anyList []*Field // field list; or nilClosing token.Pos // position of closing parenthesis/brace, if any}func (f *FieldList) Pos() token.Pos {if f.Opening.IsValid() {return f.Opening}// the list should not be empty in this case;// be conservative and guard against bad ASTsif len(f.List) > 0 {return f.List[0].Pos()}return token.NoPos}func (f *FieldList) End() token.Pos {if f.Closing.IsValid() {return f.Closing + 1}// the list should not be empty in this case;// be conservative and guard against bad ASTsif n := len(f.List); n > 0 {return f.List[n-1].End()}return token.NoPos}// NumFields returns the number of (named and anonymous fields) in a FieldList.func (f *FieldList) NumFields() int {n := 0if f != nil {for _, g := range f.List {m := len(g.Names)if m == 0 {m = 1 // anonymous field}n += m}}return n}// 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 {From, To token.Pos // position range of bad expression}// An Ident node represents an identifier.Ident struct {NamePos token.Pos // identifier positionName string // identifier nameObj *Object // denoted object; or nil}// An Ellipsis node stands for the "..." type in a// parameter list or the "..." length in an array type.//Ellipsis struct {Ellipsis token.Pos // position of "..."Elt Expr // ellipsis element type (parameter lists only); or nil}// A BasicLit node represents a literal of basic type.BasicLit struct {ValuePos token.Pos // literal positionKind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRINGValue string // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`}// A FuncLit node represents a function literal.FuncLit struct {Type *FuncType // function typeBody *BlockStmt // function body}// A CompositeLit node represents a composite literal.CompositeLit struct {Type Expr // literal type; or nilLbrace token.Pos // position of "{"Elts []Expr // list of composite elements; or nilRbrace token.Pos // position of "}"}// A ParenExpr node represents a parenthesized expression.ParenExpr struct {Lparen token.Pos // position of "("X Expr // parenthesized expressionRparen token.Pos // position of ")"}// A SelectorExpr node represents an expression followed by a selector.SelectorExpr struct {X Expr // expressionSel *Ident // field selector}// An IndexExpr node represents an expression followed by an index.IndexExpr struct {X Expr // expressionLbrack token.Pos // position of "["Index Expr // index expressionRbrack token.Pos // position of "]"}// An SliceExpr node represents an expression followed by slice indices.SliceExpr struct {X Expr // expressionLbrack token.Pos // position of "["Low Expr // begin of slice range; or nilHigh Expr // end of slice range; or nilRbrack token.Pos // position of "]"}// A TypeAssertExpr node represents an expression followed by a// type assertion.//TypeAssertExpr struct {X Expr // expressionType 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 expressionLparen token.Pos // position of "("Args []Expr // function arguments; or nilEllipsis token.Pos // position of "...", if anyRparen token.Pos // position of ")"}// A StarExpr node represents an expression of the form "*" Expression.// Semantically it could be a unary "*" expression, or a pointer type.//StarExpr struct {Star token.Pos // position of "*"X Expr // operand}// A UnaryExpr node represents a unary expression.// Unary "*" expressions are represented via StarExpr nodes.//UnaryExpr struct {OpPos token.Pos // position of OpOp token.Token // operatorX Expr // operand}// A BinaryExpr node represents a binary expression.BinaryExpr struct {X Expr // left operandOpPos token.Pos // position of OpOp token.Token // operatorY Expr // right operand}// A KeyValueExpr node represents (key : value) pairs// in composite literals.//KeyValueExpr struct {Key ExprColon token.Pos // position of ":"Value Expr})// The direction of a channel type is indicated by one// of the following constants.//type ChanDir intconst (SEND ChanDir = 1 << iotaRECV)// 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 {Lbrack token.Pos // position of "["Len Expr // Ellipsis node for [...]T array types, nil for slice typesElt Expr // element type}// A StructType node represents a struct type.StructType struct {Struct token.Pos // position of "struct" keywordFields *FieldList // list of field declarationsIncomplete 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 {Func token.Pos // position of "func" keywordParams *FieldList // (incoming) parameters; or nilResults *FieldList // (outgoing) results; or nil}// An InterfaceType node represents an interface type.InterfaceType struct {Interface token.Pos // position of "interface" keywordMethods *FieldList // list of methodsIncomplete bool // true if (source) methods are missing in the Methods list}// A MapType node represents a map type.MapType struct {Map token.Pos // position of "map" keywordKey ExprValue Expr}// A ChanType node represents a channel type.ChanType struct {Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)Dir ChanDir // channel directionValue Expr // value type})// Pos and End implementations for expression/type nodes.//func (x *BadExpr) Pos() token.Pos { return x.From }func (x *Ident) Pos() token.Pos { return x.NamePos }func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }func (x *BasicLit) Pos() token.Pos { return x.ValuePos }func (x *FuncLit) Pos() token.Pos { return x.Type.Pos() }func (x *CompositeLit) Pos() token.Pos {if x.Type != nil {return x.Type.Pos()}return x.Lbrace}func (x *ParenExpr) Pos() token.Pos { return x.Lparen }func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() }func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() }func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() }func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() }func (x *StarExpr) Pos() token.Pos { return x.Star }func (x *UnaryExpr) Pos() token.Pos { return x.OpPos }func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() }func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() }func (x *ArrayType) Pos() token.Pos { return x.Lbrack }func (x *StructType) Pos() token.Pos { return x.Struct }func (x *FuncType) Pos() token.Pos { return x.Func }func (x *InterfaceType) Pos() token.Pos { return x.Interface }func (x *MapType) Pos() token.Pos { return x.Map }func (x *ChanType) Pos() token.Pos { return x.Begin }func (x *BadExpr) End() token.Pos { return x.To }func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) }func (x *Ellipsis) End() token.Pos {if x.Elt != nil {return x.Elt.End()}return x.Ellipsis + 3 // len("...")}func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) }func (x *FuncLit) End() token.Pos { return x.Body.End() }func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 }func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 }func (x *SelectorExpr) End() token.Pos { return x.Sel.End() }func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 }func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 }func (x *TypeAssertExpr) End() token.Pos {if x.Type != nil {return x.Type.End()}return x.X.End()}func (x *CallExpr) End() token.Pos { return x.Rparen + 1 }func (x *StarExpr) End() token.Pos { return x.X.End() }func (x *UnaryExpr) End() token.Pos { return x.X.End() }func (x *BinaryExpr) End() token.Pos { return x.Y.End() }func (x *KeyValueExpr) End() token.Pos { return x.Value.End() }func (x *ArrayType) End() token.Pos { return x.Elt.End() }func (x *StructType) End() token.Pos { return x.Fields.End() }func (x *FuncType) End() token.Pos {if x.Results != nil {return x.Results.End()}return x.Params.End()}func (x *InterfaceType) End() token.Pos { return x.Methods.End() }func (x *MapType) End() token.Pos { return x.Value.End() }func (x *ChanType) End() token.Pos { return x.Value.End() }// exprNode() ensures that only expression/type nodes can be// assigned to an ExprNode.//func (*BadExpr) exprNode() {}func (*Ident) exprNode() {}func (*Ellipsis) exprNode() {}func (*BasicLit) exprNode() {}func (*FuncLit) exprNode() {}func (*CompositeLit) exprNode() {}func (*ParenExpr) exprNode() {}func (*SelectorExpr) exprNode() {}func (*IndexExpr) exprNode() {}func (*SliceExpr) exprNode() {}func (*TypeAssertExpr) exprNode() {}func (*CallExpr) exprNode() {}func (*StarExpr) exprNode() {}func (*UnaryExpr) exprNode() {}func (*BinaryExpr) exprNode() {}func (*KeyValueExpr) exprNode() {}func (*ArrayType) exprNode() {}func (*StructType) exprNode() {}func (*FuncType) exprNode() {}func (*InterfaceType) exprNode() {}func (*MapType) exprNode() {}func (*ChanType) exprNode() {}// ----------------------------------------------------------------------------// Convenience functions for Identsvar noPos token.Pos// NewIdent creates a new Ident without position.// Useful for ASTs generated by code other than the Go parser.//func NewIdent(name string) *Ident { return &Ident{noPos, name, nil} }// 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 id is an exported Go symbol// (i.e., whether it begins with an uppercase letter).//func (id *Ident) IsExported() bool { return IsExported(id.Name) }func (id *Ident) String() string {if id != nil {return id.Name}return "<nil>"}// ----------------------------------------------------------------------------// 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 {From, To token.Pos // position range 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 preceding semicolon.//EmptyStmt struct {Semicolon token.Pos // position of preceding ";"}// A LabeledStmt node represents a labeled statement.LabeledStmt struct {Label *IdentColon token.Pos // position of ":"Stmt Stmt}// An ExprStmt node represents a (stand-alone) expression// in a statement list.//ExprStmt struct {X Expr // expression}// A SendStmt node represents a send statement.SendStmt struct {Chan ExprArrow token.Pos // position of "<-"Value Expr}// An IncDecStmt node represents an increment or decrement statement.IncDecStmt struct {X ExprTokPos token.Pos // position of TokTok token.Token // INC or DEC}// An AssignStmt node represents an assignment or// a short variable declaration.//AssignStmt struct {Lhs []ExprTokPos token.Pos // position of TokTok token.Token // assignment token, DEFINERhs []Expr}// A GoStmt node represents a go statement.GoStmt struct {Go token.Pos // position of "go" keywordCall *CallExpr}// A DeferStmt node represents a defer statement.DeferStmt struct {Defer token.Pos // position of "defer" keywordCall *CallExpr}// A ReturnStmt node represents a return statement.ReturnStmt struct {Return token.Pos // position of "return" keywordResults []Expr // result expressions; or nil}// A BranchStmt node represents a break, continue, goto,// or fallthrough statement.//BranchStmt struct {TokPos token.Pos // position of TokTok token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)Label *Ident // label name; or nil}// A BlockStmt node represents a braced statement list.BlockStmt struct {Lbrace token.Pos // position of "{"List []StmtRbrace token.Pos // position of "}"}// An IfStmt node represents an if statement.IfStmt struct {If token.Pos // position of "if" keywordInit Stmt // initialization statement; or nilCond Expr // conditionBody *BlockStmtElse Stmt // else branch; or nil}// A CaseClause represents a case of an expression or type switch statement.CaseClause struct {Case token.Pos // position of "case" or "default" keywordList []Expr // list of expressions or types; nil means default caseColon token.Pos // position of ":"Body []Stmt // statement list; or nil}// A SwitchStmt node represents an expression switch statement.SwitchStmt struct {Switch token.Pos // position of "switch" keywordInit Stmt // initialization statement; or nilTag Expr // tag expression; or nilBody *BlockStmt // CaseClauses only}// An TypeSwitchStmt node represents a type switch statement.TypeSwitchStmt struct {Switch token.Pos // position of "switch" keywordInit Stmt // initialization statement; or nilAssign Stmt // x := y.(type) or y.(type)Body *BlockStmt // CaseClauses only}// A CommClause node represents a case of a select statement.CommClause struct {Case token.Pos // position of "case" or "default" keywordComm Stmt // send or receive statement; nil means default caseColon token.Pos // position of ":"Body []Stmt // statement list; or nil}// An SelectStmt node represents a select statement.SelectStmt struct {Select token.Pos // position of "select" keywordBody *BlockStmt // CommClauses only}// A ForStmt represents a for statement.ForStmt struct {For token.Pos // position of "for" keywordInit Stmt // initialization statement; or nilCond Expr // condition; or nilPost Stmt // post iteration statement; or nilBody *BlockStmt}// A RangeStmt represents a for statement with a range clause.RangeStmt struct {For token.Pos // position of "for" keywordKey, Value Expr // Value may be nilTokPos token.Pos // position of TokTok token.Token // ASSIGN, DEFINEX Expr // value to range overBody *BlockStmt})// Pos and End implementations for statement nodes.//func (s *BadStmt) Pos() token.Pos { return s.From }func (s *DeclStmt) Pos() token.Pos { return s.Decl.Pos() }func (s *EmptyStmt) Pos() token.Pos { return s.Semicolon }func (s *LabeledStmt) Pos() token.Pos { return s.Label.Pos() }func (s *ExprStmt) Pos() token.Pos { return s.X.Pos() }func (s *SendStmt) Pos() token.Pos { return s.Chan.Pos() }func (s *IncDecStmt) Pos() token.Pos { return s.X.Pos() }func (s *AssignStmt) Pos() token.Pos { return s.Lhs[0].Pos() }func (s *GoStmt) Pos() token.Pos { return s.Go }func (s *DeferStmt) Pos() token.Pos { return s.Defer }func (s *ReturnStmt) Pos() token.Pos { return s.Return }func (s *BranchStmt) Pos() token.Pos { return s.TokPos }func (s *BlockStmt) Pos() token.Pos { return s.Lbrace }func (s *IfStmt) Pos() token.Pos { return s.If }func (s *CaseClause) Pos() token.Pos { return s.Case }func (s *SwitchStmt) Pos() token.Pos { return s.Switch }func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }func (s *CommClause) Pos() token.Pos { return s.Case }func (s *SelectStmt) Pos() token.Pos { return s.Select }func (s *ForStmt) Pos() token.Pos { return s.For }func (s *RangeStmt) Pos() token.Pos { return s.For }func (s *BadStmt) End() token.Pos { return s.To }func (s *DeclStmt) End() token.Pos { return s.Decl.End() }func (s *EmptyStmt) End() token.Pos {return s.Semicolon + 1 /* len(";") */}func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }func (s *ExprStmt) End() token.Pos { return s.X.End() }func (s *SendStmt) End() token.Pos { return s.Value.End() }func (s *IncDecStmt) End() token.Pos {return s.TokPos + 2 /* len("++") */}func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }func (s *GoStmt) End() token.Pos { return s.Call.End() }func (s *DeferStmt) End() token.Pos { return s.Call.End() }func (s *ReturnStmt) End() token.Pos {if n := len(s.Results); n > 0 {return s.Results[n-1].End()}return s.Return + 6 // len("return")}func (s *BranchStmt) End() token.Pos {if s.Label != nil {return s.Label.End()}return token.Pos(int(s.TokPos) + len(s.Tok.String()))}func (s *BlockStmt) End() token.Pos { return s.Rbrace + 1 }func (s *IfStmt) End() token.Pos {if s.Else != nil {return s.Else.End()}return s.Body.End()}func (s *CaseClause) End() token.Pos {if n := len(s.Body); n > 0 {return s.Body[n-1].End()}return s.Colon + 1}func (s *SwitchStmt) End() token.Pos { return s.Body.End() }func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }func (s *CommClause) End() token.Pos {if n := len(s.Body); n > 0 {return s.Body[n-1].End()}return s.Colon + 1}func (s *SelectStmt) End() token.Pos { return s.Body.End() }func (s *ForStmt) End() token.Pos { return s.Body.End() }func (s *RangeStmt) End() token.Pos { return s.Body.End() }// stmtNode() ensures that only statement nodes can be// assigned to a StmtNode.//func (*BadStmt) stmtNode() {}func (*DeclStmt) stmtNode() {}func (*EmptyStmt) stmtNode() {}func (*LabeledStmt) stmtNode() {}func (*ExprStmt) stmtNode() {}func (*SendStmt) stmtNode() {}func (*IncDecStmt) stmtNode() {}func (*AssignStmt) stmtNode() {}func (*GoStmt) stmtNode() {}func (*DeferStmt) stmtNode() {}func (*ReturnStmt) stmtNode() {}func (*BranchStmt) stmtNode() {}func (*BlockStmt) stmtNode() {}func (*IfStmt) stmtNode() {}func (*CaseClause) stmtNode() {}func (*SwitchStmt) stmtNode() {}func (*TypeSwitchStmt) stmtNode() {}func (*CommClause) stmtNode() {}func (*SelectStmt) stmtNode() {}func (*ForStmt) stmtNode() {}func (*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 {NodespecNode()}// An ImportSpec node represents a single package import.ImportSpec struct {Doc *CommentGroup // associated documentation; or nilName *Ident // local package name (including "."); or nilPath *BasicLit // import pathComment *CommentGroup // line comments; or nilEndPos token.Pos // end of spec (overrides Path.Pos if nonzero)}// A ValueSpec node represents a constant or variable declaration// (ConstSpec or VarSpec production).//ValueSpec struct {Doc *CommentGroup // associated documentation; or nilNames []*Ident // value names (len(Names) > 0)Type Expr // value type; or nilValues []Expr // initial values; or nilComment *CommentGroup // line comments; or nil}// A TypeSpec node represents a type declaration (TypeSpec production).TypeSpec struct {Doc *CommentGroup // associated documentation; or nilName *Ident // type nameType Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypesComment *CommentGroup // line comments; or nil})// Pos and End implementations for spec nodes.//func (s *ImportSpec) Pos() token.Pos {if s.Name != nil {return s.Name.Pos()}return s.Path.Pos()}func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }func (s *TypeSpec) Pos() token.Pos { return s.Name.Pos() }func (s *ImportSpec) End() token.Pos {if s.EndPos != 0 {return s.EndPos}return s.Path.End()}func (s *ValueSpec) End() token.Pos {if n := len(s.Values); n > 0 {return s.Values[n-1].End()}if s.Type != nil {return s.Type.End()}return s.Names[len(s.Names)-1].End()}func (s *TypeSpec) End() token.Pos { return s.Type.End() }// specNode() ensures that only spec nodes can be// assigned to a Spec.//func (*ImportSpec) specNode() {}func (*ValueSpec) specNode() {}func (*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 {From, To token.Pos // position range 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 nilTokPos token.Pos // position of TokTok token.Token // IMPORT, CONST, TYPE, VARLparen token.Pos // position of '(', if anySpecs []SpecRparen token.Pos // position of ')', if any}// A FuncDecl node represents a function declaration.FuncDecl struct {Doc *CommentGroup // associated documentation; or nilRecv *FieldList // receiver (methods); or nil (functions)Name *Ident // function/method nameType *FuncType // position of Func keyword, parameters and resultsBody *BlockStmt // function body; or nil (forward declaration)})// Pos and End implementations for declaration nodes.//func (d *BadDecl) Pos() token.Pos { return d.From }func (d *GenDecl) Pos() token.Pos { return d.TokPos }func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }func (d *BadDecl) End() token.Pos { return d.To }func (d *GenDecl) End() token.Pos {if d.Rparen.IsValid() {return d.Rparen + 1}return d.Specs[0].End()}func (d *FuncDecl) End() token.Pos {if d.Body != nil {return d.Body.End()}return d.Type.End()}// declNode() ensures that only declaration nodes can be// assigned to a DeclNode.//func (*BadDecl) declNode() {}func (*GenDecl) declNode() {}func (*FuncDecl) declNode() {}// ----------------------------------------------------------------------------// Files and packages// A File node represents a Go source file.//// The Comments list contains all comments in the source file in order of// appearance, including the comments that are pointed to from other nodes// via Doc and Comment fields.//type File struct {Doc *CommentGroup // associated documentation; or nilPackage token.Pos // position of "package" keywordName *Ident // package nameDecls []Decl // top-level declarations; or nilScope *Scope // package scope (this file only)Imports []*ImportSpec // imports in this fileUnresolved []*Ident // unresolved identifiers in this fileComments []*CommentGroup // list of all comments in the source file}func (f *File) Pos() token.Pos { return f.Package }func (f *File) End() token.Pos {if n := len(f.Decls); n > 0 {return f.Decls[n-1].End()}return f.Name.End()}// A Package node represents a set of source files// collectively building a Go package.//type Package struct {Name string // package nameScope *Scope // package scope across all filesImports map[string]*Object // map of package id -> package objectFiles map[string]*File // Go source files by filename}func (p *Package) Pos() token.Pos { return token.NoPos }func (p *Package) End() token.Pos { return token.NoPos }
