Imports #
"bytes"
"errors"
"go/ast"
"go/token"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"fmt"
"go/ast"
"go/build/constraint"
"go/scanner"
"go/token"
"strings"
"fmt"
"go/ast"
"go/token"
"strings"
"bytes"
"errors"
"go/ast"
"go/token"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"fmt"
"go/ast"
"go/build/constraint"
"go/scanner"
"go/token"
"strings"
"fmt"
"go/ast"
"go/token"
"strings"
const AllErrors = SpuriousErrors
const DeclarationErrors
const ImportsOnly
const PackageClauseOnly Mode = *ast.BinaryExpr
const ParseComments
const SkipObjectResolution
const SpuriousErrors
const Trace
Parsing modes for parseSimpleStmt.
const basic = iota
const debugResolve = false
var declStart = map[token.Token]bool{...}
var exprEnd = map[token.Token]bool{...}
Parsing modes for parseSimpleStmt.
const labelOk
maxNestLev is the deepest we're willing to recurse during parsing
const maxNestLev int = 1e5
const maxScopeDepth int = 1e3
Parsing modes for parseSimpleStmt.
const rangeOk
var stmtStart = map[token.Token]bool{...}
The unresolved object is a sentinel to mark identifiers that have been added to the list of unresolved identifiers. The sentinel is only used for verifying internal consistency.
var unresolved = *ast.CallExpr
A Mode value is a set of flags (or 0). They control the amount of source code parsed and other optional parser functionality.
type Mode uint
type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
A bailout panic is raised to indicate early termination. pos and msg are only populated when bailing out of object resolution.
type bailout struct {
pos token.Pos
msg string
}
type field struct {
name *ast.Ident
typ ast.Expr
}
The parser structure holds the parser's internal state.
type parser struct {
file *token.File
errors scanner.ErrorList
scanner scanner.Scanner
mode Mode
trace bool
indent int
comments []*ast.CommentGroup
leadComment *ast.CommentGroup
lineComment *ast.CommentGroup
top bool
goVersion string
pos token.Pos
tok token.Token
lit string
syncPos token.Pos
syncCnt int
exprLev int
inRhs bool
imports []*ast.ImportSpec
nestLev int
}
type resolver struct {
handle *token.File
declErr func(token.Pos, string)
pkgScope *ast.Scope
topScope *ast.Scope
unresolved []*ast.Ident
depth int
labelScope *ast.Scope
targetStack [][]*ast.Ident
}
ParseDir calls [ParseFile] for all files with names ending in ".go" in the directory specified by path and returns a map of package name -> package AST with all the packages found. If filter != nil, only the files with [fs.FileInfo] entries passing through the filter (and ending in ".go") are considered. The mode bits are passed to [ParseFile] unchanged. Position information is recorded in fset, which must not be nil. If the directory couldn't be read, a nil map and the respective error are returned. If a parse error occurred, a non-nil but incomplete map and the first error encountered are returned.
func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error)
ParseExpr is a convenience function for obtaining the AST of an expression x. The position information recorded in the AST is undefined. The filename used in error messages is the empty string. If syntax errors were found, the result is a partial AST (with [ast.Bad]* nodes representing the fragments of erroneous source code). Multiple errors are returned via a scanner.ErrorList which is sorted by source position.
func ParseExpr(x string) (ast.Expr, error)
ParseExprFrom is a convenience function for parsing an expression. The arguments have the same meaning as for [ParseFile], but the source must be a valid Go (type or value) expression. Specifically, fset must not be nil. If the source couldn't be read, the returned AST is nil and the error indicates the specific failure. If the source was read but syntax errors were found, the result is a partial AST (with [ast.Bad]* nodes representing the fragments of erroneous source code). Multiple errors are returned via a scanner.ErrorList which is sorted by source position.
func ParseExprFrom(fset *token.FileSet, filename string, src any, mode Mode) (expr ast.Expr, err error)
ParseFile parses the source code of a single Go source file and returns the corresponding [ast.File] node. The source code may be provided via the filename of the source file, or via the src parameter. If src != nil, ParseFile parses the source from src and the filename is only used when recording position information. The type of the argument for the src parameter must be string, []byte, or [io.Reader]. If src == nil, ParseFile parses the file specified by filename. The mode parameter controls the amount of source text parsed and other optional parser functionality. If the [SkipObjectResolution] mode bit is set (recommended), the object resolution phase of parsing will be skipped, causing File.Scope, File.Unresolved, and all Ident.Obj fields to be nil. Those fields are deprecated; see [ast.Object] for details. Position information is recorded in the file set fset, which must not be nil. If the source couldn't be read, the returned AST is nil and the error indicates the specific failure. If the source was read but syntax errors were found, the result is a partial AST (with [ast.Bad]* nodes representing the fragments of erroneous source code). Multiple errors are returned via a scanner.ErrorList which is sorted by source position.
func ParseFile(fset *token.FileSet, filename string, src any, mode Mode) (f *ast.File, err error)
func (r *resolver) Visit(node ast.Node) ast.Visitor
advance consumes tokens until the current token p.tok is in the 'to' set, or token.EOF. For error recovery.
func (p *parser) advance(to map[token.Token]bool)
func assert(cond bool, msg string)
func (p *parser) atComma(context string, follow token.Token) bool
func (r *resolver) closeLabelScope()
func (r *resolver) closeScope()
Consume a comment and return it and the line on which it ends.
func (p *parser) consumeComment() (comment *ast.Comment, endline int)
Consume a group of adjacent comments, add it to the parser's comments list, and return it together with the line at which the last comment in the group ends. A non-comment token or n empty lines terminate a comment group.
func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int)
decNestLev is used to track nesting depth during parsing to prevent stack exhaustion. It is used along with incNestLev in a similar fashion to how un and trace are used.
func decNestLev(p *parser)
func (r *resolver) declare(decl any, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident)
func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind)
func (p *parser) embeddedElem(x ast.Expr) ast.Expr
func (p *parser) embeddedTerm() ast.Expr
func (p *parser) error(pos token.Pos, msg string)
func (p *parser) errorExpected(pos token.Pos, msg string)
func (p *parser) expect(tok token.Token) token.Pos
expect2 is like expect, but it returns an invalid position if the expected token is not found.
func (p *parser) expect2(tok token.Token) (pos token.Pos)
expectClosing is like expect but provides a better error message for the common case of a missing comma before a newline.
func (p *parser) expectClosing(tok token.Token, context string) token.Pos
expectSemi consumes a semicolon and returns the applicable line comment.
func (p *parser) expectSemi() (comment *ast.CommentGroup)
extractName splits the expression x into (name, expr) if syntactically x can be written as name expr. The split only happens if expr is a type element (per the isTypeElem predicate) or if force is set. If x is just a name, the result is (name, nil). If the split succeeds, the result is (name, expr). Otherwise the result is (nil, x). Examples: x force name expr ------------------------------------ P*[]int T/F P *[]int P*E T P *E P*E F nil P*E P([]int) T/F P ([]int) P(E) T P (E) P(E) F nil P(E) P*E|F|~G T/F P *E|F|~G P*E|F|G T P *E|F|G P*E|F|G F nil P*E|F|G
func extractName(x ast.Expr, force bool) (*ast.Ident, ast.Expr)
func incNestLev(p *parser) *parser
func (p *parser) init(file *token.File, src []byte, mode Mode)
isTypeElem reports whether x is a (possibly parenthesized) type element expression. The result is false if x could be a type element OR an ordinary (value) expression.
func isTypeElem(x ast.Expr) bool
func isTypeSwitchAssert(x ast.Expr) bool
func (p *parser) isTypeSwitchGuard(s ast.Stmt) bool
func (p *parser) makeExpr(s ast.Stmt, want string) ast.Expr
Advance to the next non-comment token. In the process, collect any comment groups encountered, and remember the last lead and line comments. A lead comment is a comment group that starts and ends in a line without any other tokens and that is followed by a non-comment token on the line immediately after the comment group. A line comment is a comment group that follows a non-comment token on the same line, and that has no tokens after it on the line where it ends. Lead and line comments may be considered documentation that is stored in the AST.
func (p *parser) next()
Advance to the next token.
func (p *parser) next0()
func (r *resolver) openLabelScope()
func (r *resolver) openScope(pos token.Pos)
packIndexExpr returns an IndexExpr x[expr0] or IndexListExpr x[expr0, ...].
func packIndexExpr(x ast.Expr, lbrack token.Pos, exprs []ast.Expr, rbrack token.Pos) ast.Expr
func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Expr)
"[" has already been consumed, and lbrack is its position. If len != nil it is the already consumed array length.
func (p *parser) parseArrayType(lbrack token.Pos, len ast.Expr) *ast.ArrayType
parseBinaryExpr parses a (possibly) binary expression. If x is non-nil, it is used as the left operand. TODO(rfindley): parseBinaryExpr has become overloaded. Consider refactoring.
func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int) ast.Expr
func (p *parser) parseBlockStmt() *ast.BlockStmt
func (p *parser) parseBody() *ast.BlockStmt
func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt
func (p *parser) parseCallExpr(callType string) *ast.CallExpr
func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr
func (p *parser) parseCaseClause() *ast.CaseClause
func (p *parser) parseChanType() *ast.ChanType
func (p *parser) parseCommClause() *ast.CommClause
func (p *parser) parseDecl(sync map[token.Token]bool) ast.Decl
func (p *parser) parseDeferStmt() ast.Stmt
func (p *parser) parseDotsType() *ast.Ellipsis
func (p *parser) parseElement() ast.Expr
func (p *parser) parseElementList() (list []ast.Expr)
The result may be a type or even a raw type ([...]int).
func (p *parser) parseExpr() ast.Expr
If lhs is set, result list elements which are identifiers are not resolved.
func (p *parser) parseExprList() (list []ast.Expr)
func (p *parser) parseFieldDecl() *ast.Field
func (p *parser) parseFile() *ast.File
func (p *parser) parseForStmt() ast.Stmt
func (p *parser) parseFuncDecl() *ast.FuncDecl
func (p *parser) parseFuncType() *ast.FuncType
func (p *parser) parseFuncTypeOrLit() ast.Expr
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl
func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, typ0 ast.Expr)
func (p *parser) parseGoStmt() ast.Stmt
func (p *parser) parseIdent() *ast.Ident
func (p *parser) parseIdentList() (list []*ast.Ident)
parseIfHeader is an adjusted version of parser.header in cmd/compile/internal/syntax/parser.go, which has been tuned for better error handling.
func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr)
func (p *parser) parseIfStmt() *ast.IfStmt
func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec
func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr
func (p *parser) parseInterfaceType() *ast.InterfaceType
func (p *parser) parseList(inRhs bool) []ast.Expr
func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr
func (p *parser) parseMapType() *ast.MapType
func (p *parser) parseMethodSpec() *ast.Field
parseOperand may return an expression or a raw type (incl. array types of the form [...]T). Callers must verify the result.
func (p *parser) parseOperand() ast.Expr
func (p *parser) parseParamDecl(name *ast.Ident, typeSetsOK bool) (f field)
func (p *parser) parseParameterList(name0 *ast.Ident, typ0 ast.Expr, closing token.Token) (params []*ast.Field)
func (p *parser) parseParameters(acceptTParams bool) (tparams *ast.FieldList, params *ast.FieldList)
func (p *parser) parsePointerType() *ast.StarExpr
func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr
func (p *parser) parseQualifiedIdent(ident *ast.Ident) ast.Expr
func (p *parser) parseResult() *ast.FieldList
func (p *parser) parseReturnStmt() *ast.ReturnStmt
func (p *parser) parseRhs() ast.Expr
func (p *parser) parseSelectStmt() *ast.SelectStmt
func (p *parser) parseSelector(x ast.Expr) ast.Expr
parseSimpleStmt returns true as 2nd result if it parsed the assignment of a range clause (with mode == rangeOk). The returned statement is an assignment with a right-hand side that is a single unary expression of the form "range x". No guarantees are given for the left-hand side.
func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool)
func (p *parser) parseStmt() (s ast.Stmt)
func (p *parser) parseStmtList() (list []ast.Stmt)
func (p *parser) parseStructType() *ast.StructType
func (p *parser) parseSwitchStmt() ast.Stmt
func (p *parser) parseType() ast.Expr
func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr
func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr
If the result is an identifier, it is not resolved.
func (p *parser) parseTypeName(ident *ast.Ident) ast.Expr
func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec
func (p *parser) parseUnaryExpr() ast.Expr
func (p *parser) parseValue() ast.Expr
func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
func (p *parser) printTrace(a ...any)
If src != nil, readSource converts src to a []byte if possible; otherwise it returns an error. If src == nil, readSource returns the result of reading the file specified by filename.
func readSource(filename string, src any) ([]byte, error)
If x is an identifier, resolve attempts to resolve x by looking up the object it denotes. If no object is found and collectUnresolved is set, x is marked as unresolved and collected in the list of unresolved identifiers.
func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool)
resolveFile walks the given file to resolve identifiers within the file scope, updating ast.Ident.Obj fields with declaration information. If declErr is non-nil, it is used to report declaration errors during resolution. tok is used to format position in error messages.
func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string))
func (r *resolver) resolveList(list *ast.FieldList)
safePos returns a valid file position for a given position: If pos is valid to begin with, safePos returns pos. If pos is out-of-range, safePos returns the EOF position. This is hack to work around "artificial" end positions in the AST which are computed by adding 1 to (presumably valid) token positions. If the token positions are invalid due to parse errors, the resulting end position may be past the file's EOF position, which would lead to panics if used later on.
func (p *parser) safePos(pos token.Pos) (res token.Pos)
func (r *resolver) shortVarDecl(decl *ast.AssignStmt)
func (r *resolver) sprintf(format string, args ...any) string
func (p *parser) tokPrec() (token.Token, int)
func trace(p *parser, msg string) *parser
func (r *resolver) trace(format string, args ...any)
func (p *parser) tryIdentOrType() ast.Expr
Usage pattern: defer un(trace(p, "..."))
func un(p *parser)
func (r *resolver) walkBody(body *ast.BlockStmt)
func (r *resolver) walkExprs(list []ast.Expr)
func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind)
func (r *resolver) walkFuncType(typ *ast.FuncType)
func (r *resolver) walkLHS(list []ast.Expr)
func (r *resolver) walkRecv(recv *ast.FieldList)
func (r *resolver) walkStmts(list []ast.Stmt)
walkTParams is like walkFieldList, but declares type parameters eagerly so that they may be resolved in the constraint expressions held in the field Type.
func (r *resolver) walkTParams(list *ast.FieldList)
Generated with Arrow