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 parser implements a parser for Go source files. Input may be provided in a variety of forms (see the various Parse* functions); the output is an abstract syntax tree (AST) representing the Go source. The parser is invoked through one of the Parse* functions. The parser accepts a larger language than is syntactically permitted by the Go spec, for simplicity, and for improved robustness in the presence of syntax errors. For instance, in method declarations, the receiver is treated like an ordinary parameter list and thus may contain multiple entries where the spec permits exactly one. Consequently, the corresponding field in the AST (ast.FuncDecl.Recv) field is not restricted to one entry.
package parser

import (
	
	
	
	
	
	
	
)
The parser structure holds the parser's internal state.
Tracing/debugging
	mode   Mode // parsing mode
	trace  bool // == (mode & Trace != 0)
	indent int  // indentation used for tracing output
Comments
	comments    []*ast.CommentGroup
	leadComment *ast.CommentGroup // last lead comment
	lineComment *ast.CommentGroup // last line comment
Next token
	pos token.Pos   // token position
	tok token.Token // one token look-ahead
	lit string      // token literal
Error recovery (used to limit the number of calls to parser.advance w/o making scanning progress - avoids potential endless loops across multiple parser functions during error recovery)
	syncPos token.Pos // last synchronization position
	syncCnt int       // number of parser.advance calls without progress
Non-syntactic parser control
	exprLev int  // < 0: in control clause, >= 0: in expression
	inRhs   bool // if set, the parser is parsing a rhs expression
Ordinary identifier scopes
	pkgScope   *ast.Scope        // pkgScope.Outer == nil
	topScope   *ast.Scope        // top-most scope; may be pkgScope
	unresolved []*ast.Ident      // unresolved identifiers
	imports    []*ast.ImportSpec // list of imports
Label scopes (maintained by open/close LabelScope)
	labelScope  *ast.Scope     // label scope for current function
	targetStack [][]*ast.Ident // stack of unresolved labels
}

func ( *parser) ( *token.FileSet,  string,  []byte,  Mode) {
	.file = .AddFile(, -1, len())
	var  scanner.Mode
	if &ParseComments != 0 {
		 = scanner.ScanComments
	}
	 := func( token.Position,  string) { .errors.Add(, ) }
	.scanner.Init(.file, , , )

	.mode = 
	.trace = &Trace != 0 // for convenience (p.trace is used frequently)

	.next()
}
---------------------------------------------------------------------------- Scoping support
resolve labels
	 := len(.targetStack) - 1
	 := .labelScope
	for ,  := range .targetStack[] {
		.Obj = .Lookup(.Name)
		if .Obj == nil && .mode&DeclarationErrors != 0 {
			.error(.Pos(), fmt.Sprintf("label %s undefined", .Name))
		}
pop label scope
	.targetStack = .targetStack[0:]
	.labelScope = .labelScope.Outer
}

func ( *parser) (,  interface{},  *ast.Scope,  ast.ObjKind,  ...*ast.Ident) {
	for ,  := range  {
		assert(.Obj == nil, "identifier already declared or resolved")
remember the corresponding declaration for redeclaration errors and global variable resolution/typechecking phase
		.Decl = 
		.Data = 
		.Obj = 
		if .Name != "_" {
			if  := .Insert();  != nil && .mode&DeclarationErrors != 0 {
				 := ""
				if  := .Pos(); .IsValid() {
					 = fmt.Sprintf("\n\tprevious declaration at %s", .file.Position())
				}
				.error(.Pos(), fmt.Sprintf("%s redeclared in this block%s", .Name, ))
			}
		}
	}
}

Go spec: A short variable declaration may redeclare variables provided they were originally declared in the same block with the same type, and at least one of the non-blank variables is new.
	 := 0 // number of new variables
	for ,  := range  {
		if ,  := .(*ast.Ident);  {
			assert(.Obj == nil, "identifier already declared or resolved")
remember corresponding assignment for other tools
			.Decl = 
			.Obj = 
			if .Name != "_" {
				if  := .topScope.Insert();  != nil {
					.Obj =  // redeclaration
				} else {
					++ // new declaration
				}
			}
		} else {
			.errorExpected(.Pos(), "identifier on left side of :=")
		}
	}
	if  == 0 && .mode&DeclarationErrors != 0 {
		.error([0].Pos(), "no new variables on left side of :=")
	}
}
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.
If x is an identifier, tryResolve 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.
nothing to do if x is not an identifier or the blank identifier
	,  := .(*ast.Ident)
	if  == nil {
		return
	}
	assert(.Obj == nil, "identifier already declared or resolved")
	if .Name == "_" {
		return
try to resolve the identifier
	for  := .topScope;  != nil;  = .Outer {
		if  := .Lookup(.Name);  != nil {
			.Obj = 
			return
		}
all local scopes are known, so any unresolved identifier must be found either in the file scope, package scope (perhaps in another file), or universe scope --- collect them so that they can be resolved later
	if  {
		.Obj = unresolved
		.unresolved = append(.unresolved, )
	}
}

func ( *parser) ( ast.Expr) {
	.tryResolve(, true)
}
---------------------------------------------------------------------------- Parsing support

func ( *parser) ( ...interface{}) {
	const  = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
	const  = len()
	 := .file.Position(.pos)
	fmt.Printf("%5d:%3d: ", .Line, .Column)
	 := 2 * .indent
	for  >  {
		fmt.Print()
		 -= 
i <= n
	fmt.Print([0:])
	fmt.Println(...)
}

func ( *parser,  string) *parser {
	.printTrace(, "(")
	.indent++
	return 
}
Usage pattern: defer un(trace(p, "..."))
func ( *parser) {
	.indent--
	.printTrace(")")
}
Advance to the next token.
Because of one-token look-ahead, print the previous token when tracing as it provides a more readable output. The very first token (!p.pos.IsValid()) is not initialized (it is token.ILLEGAL), so don't print it .
	if .trace && .pos.IsValid() {
		 := .tok.String()
		switch {
		case .tok.IsLiteral():
			.printTrace(, .lit)
		case .tok.IsOperator(), .tok.IsKeyword():
			.printTrace("\"" +  + "\"")
		default:
			.printTrace()
		}
	}

	.pos, .tok, .lit = .scanner.Scan()
}
Consume a comment and return it and the line on which it ends.
-style comments may end on a different line than where they start. Scan the comment for '\n' chars and adjust endline accordingly.
	 = .file.Line(.pos)
don't use range here - no need to decode Unicode code points
		for  := 0;  < len(.lit); ++ {
			if .lit[] == '\n' {
				++
			}
		}
	}

	 = &ast.Comment{Slash: .pos, Text: .lit}
	.next0()

	return
}
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 ( *parser) ( int) ( *ast.CommentGroup,  int) {
	var  []*ast.Comment
	 = .file.Line(.pos)
	for .tok == token.COMMENT && .file.Line(.pos) <= + {
		var  *ast.Comment
		,  = .consumeComment()
		 = append(, )
	}
add comment group to the comments list
	 = &ast.CommentGroup{List: }
	.comments = append(.comments, )

	return
}
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 ( *parser) () {
	.leadComment = nil
	.lineComment = nil
	 := .pos
	.next0()

	if .tok == token.COMMENT {
		var  *ast.CommentGroup
		var  int

The comment is on same line as the previous token; it cannot be a lead comment but may be a line comment.
			,  = .consumeCommentGroup(0)
The next token is on a different line, thus the last comment group is a line comment.
				.lineComment = 
			}
		}
consume successor comments, if any
		 = -1
		for .tok == token.COMMENT {
			,  = .consumeCommentGroup(1)
		}

The next token is following on the line immediately after the comment group, thus the last comment group is a lead comment.
			.leadComment = 
		}
	}
}
A bailout panic is raised to indicate early termination.
type bailout struct{}

func ( *parser) ( token.Pos,  string) {
	 := .file.Position()
If AllErrors is not set, discard errors reported on the same line as the last recorded error and stop parsing if there are more than 10 errors.
	if .mode&AllErrors == 0 {
		 := len(.errors)
		if  > 0 && .errors[-1].Pos.Line == .Line {
			return // discard - likely a spurious error
		}
		if  > 10 {
			panic(bailout{})
		}
	}

	.errors.Add(, )
}

func ( *parser) ( token.Pos,  string) {
	 = "expected " + 
the error happened at the current position; make the error message more specific
		switch {
		case .tok == token.SEMICOLON && .lit == "\n":
			 += ", found newline"
print 123 rather than 'INT', etc.
			 += ", found " + .lit
		default:
			 += ", found '" + .tok.String() + "'"
		}
	}
	.error(, )
}

func ( *parser) ( token.Token) token.Pos {
	 := .pos
	if .tok !=  {
		.errorExpected(, "'"+.String()+"'")
	}
	.next() // make progress
	return 
}
expect2 is like expect, but it returns an invalid position if the expected token is not found.
func ( *parser) ( token.Token) ( token.Pos) {
	if .tok ==  {
		 = .pos
	} else {
		.errorExpected(.pos, "'"+.String()+"'")
	}
	.next() // make progress
	return
}
expectClosing is like expect but provides a better error message for the common case of a missing comma before a newline.
func ( *parser) ( token.Token,  string) token.Pos {
	if .tok !=  && .tok == token.SEMICOLON && .lit == "\n" {
		.error(.pos, "missing ',' before newline in "+)
		.next()
	}
	return .expect()
}

semicolon is optional before a closing ')' or '}'
	if .tok != token.RPAREN && .tok != token.RBRACE {
		switch .tok {
permit a ',' instead of a ';' but complain
			.errorExpected(.pos, "';'")
			fallthrough
		case token.SEMICOLON:
			.next()
		default:
			.errorExpected(.pos, "';'")
			.advance(stmtStart)
		}
	}
}

func ( *parser) ( string,  token.Token) bool {
	if .tok == token.COMMA {
		return true
	}
	if .tok !=  {
		 := "missing ','"
		if .tok == token.SEMICOLON && .lit == "\n" {
			 += " before newline"
		}
		.error(.pos, +" in "+)
		return true // "insert" comma and continue
	}
	return false
}

func ( bool,  string) {
	if ! {
		panic("go/parser internal error: " + )
	}
}
advance consumes tokens until the current token p.tok is in the 'to' set, or token.EOF. For error recovery.
func ( *parser) ( map[token.Token]bool) {
	for ; .tok != token.EOF; .next() {
Return only if parser made some progress since last sync or if it has not reached 10 advance calls without progress. Otherwise consume at least one token to avoid an endless parser loop (it is possible that both parseOperand and parseStmt call advance and correctly do not advance, thus the need for the invocation limit p.syncCnt).
			if .pos == .syncPos && .syncCnt < 10 {
				.syncCnt++
				return
			}
			if .pos > .syncPos {
				.syncPos = .pos
				.syncCnt = 0
				return
Reaching here indicates a parser bug, likely an incorrect token list in this function, but it only leads to skipping of possibly correct code if a previous error is present, and thus is preferred over a non-terminating parse.
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 ( *parser) ( token.Pos) ( token.Pos) {
	defer func() {
		if recover() != nil {
			 = token.Pos(.file.Base() + .file.Size()) // EOF position
		}
	}()
	_ = .file.Offset() // trigger a panic if position is out-of-range
	return 
}
---------------------------------------------------------------------------- Identifiers

func ( *parser) () *ast.Ident {
	 := .pos
	 := "_"
	if .tok == token.IDENT {
		 = .lit
		.next()
	} else {
		.expect(token.IDENT) // use expect() error handling
	}
	return &ast.Ident{NamePos: , Name: }
}

func ( *parser) () ( []*ast.Ident) {
	if .trace {
		defer un(trace(, "IdentList"))
	}

	 = append(, .parseIdent())
	for .tok == token.COMMA {
		.next()
		 = append(, .parseIdent())
	}

	return
}
---------------------------------------------------------------------------- Common productions
If lhs is set, result list elements which are identifiers are not resolved.
func ( *parser) ( bool) ( []ast.Expr) {
	if .trace {
		defer un(trace(, "ExpressionList"))
	}

	 = append(, .checkExpr(.parseExpr()))
	for .tok == token.COMMA {
		.next()
		 = append(, .checkExpr(.parseExpr()))
	}

	return
}

func ( *parser) () []ast.Expr {
	 := .inRhs
	.inRhs = false
	 := .parseExprList(true)
	switch .tok {
lhs of a short variable declaration but doesn't enter scope until later: caller must call p.shortVarDecl(p.makeIdentList(list)) at appropriate time.
lhs of a label declaration or a communication clause of a select statement (parseLhsList is not called when parsing the case clause of a switch statement): - labels are declared by the caller of parseLhsList - for communication clauses, if there is a stand-alone identifier followed by a colon, we have a syntax error; there is no need to resolve the identifier in that case
identifiers must be declared elsewhere
		for ,  := range  {
			.resolve()
		}
	}
	.inRhs = 
	return 
}

func ( *parser) () []ast.Expr {
	 := .inRhs
	.inRhs = true
	 := .parseExprList(false)
	.inRhs = 
	return 
}
---------------------------------------------------------------------------- Types

func ( *parser) () ast.Expr {
	if .trace {
		defer un(trace(, "Type"))
	}

	 := .tryType()

	if  == nil {
		 := .pos
		.errorExpected(, "type")
		.advance(exprEnd)
		return &ast.BadExpr{From: , To: .pos}
	}

	return 
}
If the result is an identifier, it is not resolved.
func ( *parser) () ast.Expr {
	if .trace {
		defer un(trace(, "TypeName"))
	}

don't resolve ident yet - it may be a parameter or field name

ident is a package name
		.next()
		.resolve()
		 := .parseIdent()
		return &ast.SelectorExpr{X: , Sel: }
	}

	return 
}

func ( *parser) () ast.Expr {
	if .trace {
		defer un(trace(, "ArrayType"))
	}

	 := .expect(token.LBRACK)
	.exprLev++
always permit ellipsis for more fault-tolerant parsing
	if .tok == token.ELLIPSIS {
		 = &ast.Ellipsis{Ellipsis: .pos}
		.next()
	} else if .tok != token.RBRACK {
		 = .parseRhs()
	}
	.exprLev--
	.expect(token.RBRACK)
	 := .parseType()

	return &ast.ArrayType{Lbrack: , Len: , Elt: }
}

func ( *parser) ( []ast.Expr) []*ast.Ident {
	 := make([]*ast.Ident, len())
	for ,  := range  {
		,  := .(*ast.Ident)
		if ! {
only report error if it's a new one
				.errorExpected(.Pos(), "identifier")
			}
			 = &ast.Ident{NamePos: .Pos(), Name: "_"}
		}
		[] = 
	}
	return 
}

func ( *parser) ( *ast.Scope) *ast.Field {
	if .trace {
		defer un(trace(, "FieldDecl"))
	}

	 := .leadComment
1st FieldDecl A type name used as an anonymous field looks like a field identifier.
	var  []ast.Expr
	for {
		 = append(, .parseVarType(false))
		if .tok != token.COMMA {
			break
		}
		.next()
	}

	 := .tryVarType(false)
analyze case
	var  []*ast.Ident
IdentifierList Type
		 = .makeIdentList()
["*"] TypeName (AnonymousField)
		 = [0] // we always have at least one element
		if  := len();  > 1 {
			.errorExpected(.pos, "type")
			 = &ast.BadExpr{From: .pos, To: .pos}
		} else if !isTypeName(deref()) {
			.errorExpected(.Pos(), "anonymous field")
			 = &ast.BadExpr{From: .Pos(), To: .safePos(.End())}
		}
	}
Tag
	var  *ast.BasicLit
	if .tok == token.STRING {
		 = &ast.BasicLit{ValuePos: .pos, Kind: .tok, Value: .lit}
		.next()
	}

	.expectSemi() // call before accessing p.linecomment

	 := &ast.Field{Doc: , Names: , Type: , Tag: , Comment: .lineComment}
	.declare(, nil, , ast.Var, ...)
	.resolve()

	return 
}

func ( *parser) () *ast.StructType {
	if .trace {
		defer un(trace(, "StructType"))
	}

	 := .expect(token.STRUCT)
	 := .expect(token.LBRACE)
	 := ast.NewScope(nil) // struct scope
	var  []*ast.Field
a field declaration cannot start with a '(' but we accept it here for more robust parsing and better error messages (parseFieldDecl will check and complain if necessary)
		 = append(, .parseFieldDecl())
	}
	 := .expect(token.RBRACE)

	return &ast.StructType{
		Struct: ,
		Fields: &ast.FieldList{
			Opening: ,
			List:    ,
			Closing: ,
		},
	}
}

func ( *parser) () *ast.StarExpr {
	if .trace {
		defer un(trace(, "PointerType"))
	}

	 := .expect(token.MUL)
	 := .parseType()

	return &ast.StarExpr{Star: , X: }
}
If the result is an identifier, it is not resolved.
func ( *parser) ( bool) ast.Expr {
	if  && .tok == token.ELLIPSIS {
		 := .pos
		.next()
		 := .tryIdentOrType() // don't use parseType so we can provide better error message
		if  != nil {
			.resolve()
		} else {
			.error(, "'...' parameter is missing type")
			 = &ast.BadExpr{From: , To: .pos}
		}
		return &ast.Ellipsis{Ellipsis: , Elt: }
	}
	return .tryIdentOrType()
}
If the result is an identifier, it is not resolved.
func ( *parser) ( bool) ast.Expr {
	 := .tryVarType()
	if  == nil {
		 := .pos
		.errorExpected(, "type")
		.next() // make progress
		 = &ast.BadExpr{From: , To: .pos}
	}
	return 
}

func ( *parser) ( *ast.Scope,  bool) ( []*ast.Field) {
	if .trace {
		defer un(trace(, "ParameterList"))
	}
1st ParameterDecl A list of identifiers looks like a list of type names.
	var  []ast.Expr
	for {
		 = append(, .parseVarType())
		if .tok != token.COMMA {
			break
		}
		.next()
		if .tok == token.RPAREN {
			break
		}
	}
analyze case
IdentifierList Type
		 := .makeIdentList()
		 := &ast.Field{Names: , Type: }
Go spec: The scope of an identifier denoting a function parameter or result variable is the function body.
		.declare(, nil, , ast.Var, ...)
		.resolve()
		if !.atComma("parameter list", token.RPAREN) {
			return
		}
		.next()
		for .tok != token.RPAREN && .tok != token.EOF {
			 := .parseIdentList()
			 := .parseVarType()
			 := &ast.Field{Names: , Type: }
Go spec: The scope of an identifier denoting a function parameter or result variable is the function body.
			.declare(, nil, , ast.Var, ...)
			.resolve()
			if !.atComma("parameter list", token.RPAREN) {
				break
			}
			.next()
		}
		return
	}
Type { "," Type } (anonymous parameters)
	 = make([]*ast.Field, len())
	for ,  := range  {
		.resolve()
		[] = &ast.Field{Type: }
	}
	return
}

func ( *parser) ( *ast.Scope,  bool) *ast.FieldList {
	if .trace {
		defer un(trace(, "Parameters"))
	}

	var  []*ast.Field
	 := .expect(token.LPAREN)
	if .tok != token.RPAREN {
		 = .parseParameterList(, )
	}
	 := .expect(token.RPAREN)

	return &ast.FieldList{Opening: , List: , Closing: }
}

func ( *parser) ( *ast.Scope) *ast.FieldList {
	if .trace {
		defer un(trace(, "Result"))
	}

	if .tok == token.LPAREN {
		return .parseParameters(, false)
	}

	 := .tryType()
	if  != nil {
		 := make([]*ast.Field, 1)
		[0] = &ast.Field{Type: }
		return &ast.FieldList{List: }
	}

	return nil
}

func ( *parser) ( *ast.Scope) (,  *ast.FieldList) {
	if .trace {
		defer un(trace(, "Signature"))
	}

	 = .parseParameters(, true)
	 = .parseResult()

	return
}

func ( *parser) () (*ast.FuncType, *ast.Scope) {
	if .trace {
		defer un(trace(, "FuncType"))
	}

	 := .expect(token.FUNC)
	 := ast.NewScope(.topScope) // function scope
	,  := .parseSignature()

	return &ast.FuncType{Func: , Params: , Results: }, 
}

func ( *parser) ( *ast.Scope) *ast.Field {
	if .trace {
		defer un(trace(, "MethodSpec"))
	}

	 := .leadComment
	var  []*ast.Ident
	var  ast.Expr
	 := .parseTypeName()
method
		 = []*ast.Ident{}
		 := ast.NewScope(nil) // method scope
		,  := .parseSignature()
		 = &ast.FuncType{Func: token.NoPos, Params: , Results: }
embedded interface
		 = 
		.resolve()
	}
	.expectSemi() // call before accessing p.linecomment

	 := &ast.Field{Doc: , Names: , Type: , Comment: .lineComment}
	.declare(, nil, , ast.Fun, ...)

	return 
}

func ( *parser) () *ast.InterfaceType {
	if .trace {
		defer un(trace(, "InterfaceType"))
	}

	 := .expect(token.INTERFACE)
	 := .expect(token.LBRACE)
	 := ast.NewScope(nil) // interface scope
	var  []*ast.Field
	for .tok == token.IDENT {
		 = append(, .parseMethodSpec())
	}
	 := .expect(token.RBRACE)

	return &ast.InterfaceType{
		Interface: ,
		Methods: &ast.FieldList{
			Opening: ,
			List:    ,
			Closing: ,
		},
	}
}

func ( *parser) () *ast.MapType {
	if .trace {
		defer un(trace(, "MapType"))
	}

	 := .expect(token.MAP)
	.expect(token.LBRACK)
	 := .parseType()
	.expect(token.RBRACK)
	 := .parseType()

	return &ast.MapType{Map: , Key: , Value: }
}

func ( *parser) () *ast.ChanType {
	if .trace {
		defer un(trace(, "ChanType"))
	}

	 := .pos
	 := ast.SEND | ast.RECV
	var  token.Pos
	if .tok == token.CHAN {
		.next()
		if .tok == token.ARROW {
			 = .pos
			.next()
			 = ast.SEND
		}
	} else {
		 = .expect(token.ARROW)
		.expect(token.CHAN)
		 = ast.RECV
	}
	 := .parseType()

	return &ast.ChanType{Begin: , Arrow: , Dir: , Value: }
}
If the result is an identifier, it is not resolved.
func ( *parser) () ast.Expr {
	switch .tok {
	case token.IDENT:
		return .parseTypeName()
	case token.LBRACK:
		return .parseArrayType()
	case token.STRUCT:
		return .parseStructType()
	case token.MUL:
		return .parsePointerType()
	case token.FUNC:
		,  := .parseFuncType()
		return 
	case token.INTERFACE:
		return .parseInterfaceType()
	case token.MAP:
		return .parseMapType()
	case token.CHAN, token.ARROW:
		return .parseChanType()
	case token.LPAREN:
		 := .pos
		.next()
		 := .parseType()
		 := .expect(token.RPAREN)
		return &ast.ParenExpr{Lparen: , X: , Rparen: }
	}
no type found
	return nil
}

func ( *parser) () ast.Expr {
	 := .tryIdentOrType()
	if  != nil {
		.resolve()
	}
	return 
}
---------------------------------------------------------------------------- Blocks

func ( *parser) () ( []ast.Stmt) {
	if .trace {
		defer un(trace(, "StatementList"))
	}

	for .tok != token.CASE && .tok != token.DEFAULT && .tok != token.RBRACE && .tok != token.EOF {
		 = append(, .parseStmt())
	}

	return
}

func ( *parser) ( *ast.Scope) *ast.BlockStmt {
	if .trace {
		defer un(trace(, "Body"))
	}

	 := .expect(token.LBRACE)
	.topScope =  // open function scope
	.openLabelScope()
	 := .parseStmtList()
	.closeLabelScope()
	.closeScope()
	 := .expect2(token.RBRACE)

	return &ast.BlockStmt{Lbrace: , List: , Rbrace: }
}

func ( *parser) () *ast.BlockStmt {
	if .trace {
		defer un(trace(, "BlockStmt"))
	}

	 := .expect(token.LBRACE)
	.openScope()
	 := .parseStmtList()
	.closeScope()
	 := .expect2(token.RBRACE)

	return &ast.BlockStmt{Lbrace: , List: , Rbrace: }
}
---------------------------------------------------------------------------- Expressions

func ( *parser) () ast.Expr {
	if .trace {
		defer un(trace(, "FuncTypeOrLit"))
	}

	,  := .parseFuncType()
function type only
		return 
	}

	.exprLev++
	 := .parseBody()
	.exprLev--

	return &ast.FuncLit{Type: , Body: }
}
parseOperand may return an expression or a raw type (incl. array types of the form [...]T. Callers must verify the result. If lhs is set and the result is an identifier, it is not resolved.
func ( *parser) ( bool) ast.Expr {
	if .trace {
		defer un(trace(, "Operand"))
	}

	switch .tok {
	case token.IDENT:
		 := .parseIdent()
		if ! {
			.resolve()
		}
		return 

	case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
		 := &ast.BasicLit{ValuePos: .pos, Kind: .tok, Value: .lit}
		.next()
		return 

	case token.LPAREN:
		 := .pos
		.next()
		.exprLev++
		 := .parseRhsOrType() // types may be parenthesized: (some type)
		.exprLev--
		 := .expect(token.RPAREN)
		return &ast.ParenExpr{Lparen: , X: , Rparen: }

	case token.FUNC:
		return .parseFuncTypeOrLit()
	}

could be type for composite literal or conversion
		,  := .(*ast.Ident)
		assert(!, "type cannot be identifier")
		return 
	}
we have an error
	 := .pos
	.errorExpected(, "operand")
	.advance(stmtStart)
	return &ast.BadExpr{From: , To: .pos}
}

func ( *parser) ( ast.Expr) ast.Expr {
	if .trace {
		defer un(trace(, "Selector"))
	}

	 := .parseIdent()

	return &ast.SelectorExpr{X: , Sel: }
}

func ( *parser) ( ast.Expr) ast.Expr {
	if .trace {
		defer un(trace(, "TypeAssertion"))
	}

	 := .expect(token.LPAREN)
	var  ast.Expr
type switch: typ == nil
		.next()
	} else {
		 = .parseType()
	}
	 := .expect(token.RPAREN)

	return &ast.TypeAssertExpr{X: , Type: , Lparen: , Rparen: }
}

func ( *parser) ( ast.Expr) ast.Expr {
	if .trace {
		defer un(trace(, "IndexOrSlice"))
	}

	const  = 3 // change the 3 to 2 to disable 3-index slices
	 := .expect(token.LBRACK)
	.exprLev++
	var  []ast.Expr
	var  [ - 1]token.Pos
	if .tok != token.COLON {
		[0] = .parseRhs()
	}
	 := 0
	for .tok == token.COLON &&  < len() {
		[] = .pos
		++
		.next()
		if .tok != token.COLON && .tok != token.RBRACK && .tok != token.EOF {
			[] = .parseRhs()
		}
	}
	.exprLev--
	 := .expect(token.RBRACK)

slice expression
		 := false
		if  == 2 {
Check presence of 2nd and 3rd index here rather than during type-checking to prevent erroneous programs from passing through gofmt (was issue 7305).
			if [1] == nil {
				.error([0], "2nd index required in 3-index slice")
				[1] = &ast.BadExpr{From: [0] + 1, To: [1]}
			}
			if [2] == nil {
				.error([1], "3rd index required in 3-index slice")
				[2] = &ast.BadExpr{From: [1] + 1, To: }
			}
		}
		return &ast.SliceExpr{X: , Lbrack: , Low: [0], High: [1], Max: [2], Slice3: , Rbrack: }
	}

	return &ast.IndexExpr{X: , Lbrack: , Index: [0], Rbrack: }
}

func ( *parser) ( ast.Expr) *ast.CallExpr {
	if .trace {
		defer un(trace(, "CallOrConversion"))
	}

	 := .expect(token.LPAREN)
	.exprLev++
	var  []ast.Expr
	var  token.Pos
	for .tok != token.RPAREN && .tok != token.EOF && !.IsValid() {
		 = append(, .parseRhsOrType()) // builtins may expect a type: make(some type, ...)
		if .tok == token.ELLIPSIS {
			 = .pos
			.next()
		}
		if !.atComma("argument list", token.RPAREN) {
			break
		}
		.next()
	}
	.exprLev--
	 := .expectClosing(token.RPAREN, "argument list")

	return &ast.CallExpr{Fun: , Lparen: , Args: , Ellipsis: , Rparen: }
}

func ( *parser) ( bool) ast.Expr {
	if .trace {
		defer un(trace(, "Element"))
	}

	if .tok == token.LBRACE {
		return .parseLiteralValue(nil)
	}
Because the parser doesn't know the composite literal type, it cannot know if a key that's an identifier is a struct field name or a name denoting a value. The former is not resolved by the parser or the resolver. Instead, _try_ to resolve such a key if possible. If it resolves, it a) has correctly resolved, or b) incorrectly resolved because the key is a struct field with a name matching another identifier. In the former case we are done, and in the latter case we don't care because the type checker will do a separate field lookup. If the key does not resolve, it a) must be defined at the top level in another file of the same package, the universe scope, or be undeclared; or b) it is a struct field. In the former case, the type checker can do a top-level lookup, and in the latter case it will do a separate field lookup.
	 := .checkExpr(.parseExpr())
	if  {
Try to resolve the key but don't collect it as unresolved identifier if it fails so that we don't get (possibly false) errors about undeclared names.
not a key
			.resolve()
		}
	}

	return 
}

func ( *parser) () ast.Expr {
	if .trace {
		defer un(trace(, "Element"))
	}

	 := .parseValue(true)
	if .tok == token.COLON {
		 := .pos
		.next()
		 = &ast.KeyValueExpr{Key: , Colon: , Value: .parseValue(false)}
	}

	return 
}

func ( *parser) () ( []ast.Expr) {
	if .trace {
		defer un(trace(, "ElementList"))
	}

	for .tok != token.RBRACE && .tok != token.EOF {
		 = append(, .parseElement())
		if !.atComma("composite literal", token.RBRACE) {
			break
		}
		.next()
	}

	return
}

func ( *parser) ( ast.Expr) ast.Expr {
	if .trace {
		defer un(trace(, "LiteralValue"))
	}

	 := .expect(token.LBRACE)
	var  []ast.Expr
	.exprLev++
	if .tok != token.RBRACE {
		 = .parseElementList()
	}
	.exprLev--
	 := .expectClosing(token.RBRACE, "composite literal")
	return &ast.CompositeLit{Type: , Lbrace: , Elts: , Rbrace: }
}
checkExpr checks that x is an expression (and not a type).
func ( *parser) ( ast.Expr) ast.Expr {
	switch unparen().(type) {
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.BasicLit:
	case *ast.FuncLit:
	case *ast.CompositeLit:
	case *ast.ParenExpr:
		panic("unreachable")
	case *ast.SelectorExpr:
	case *ast.IndexExpr:
	case *ast.SliceExpr:
If t.Type == nil we have a type assertion of the form y.(type), which is only allowed in type switch expressions. It's hard to exclude those but for the case where we are in a type switch. Instead be lenient and test this in the type checker.
	case *ast.CallExpr:
	case *ast.StarExpr:
	case *ast.UnaryExpr:
	case *ast.BinaryExpr:
all other nodes are not proper expressions
		.errorExpected(.Pos(), "expression")
		 = &ast.BadExpr{From: .Pos(), To: .safePos(.End())}
	}
	return 
}
isTypeName reports whether x is a (qualified) TypeName.
func ( ast.Expr) bool {
	switch t := .(type) {
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.SelectorExpr:
		,  := .X.(*ast.Ident)
		return 
	default:
		return false // all other nodes are not type names
	}
	return true
}
isLiteralType reports whether x is a legal composite literal type.
func ( ast.Expr) bool {
	switch t := .(type) {
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.SelectorExpr:
		,  := .X.(*ast.Ident)
		return 
	case *ast.ArrayType:
	case *ast.StructType:
	case *ast.MapType:
	default:
		return false // all other nodes are not legal composite literal types
	}
	return true
}
If x is of the form *T, deref returns T, otherwise it returns x.
func ( ast.Expr) ast.Expr {
	if ,  := .(*ast.StarExpr);  {
		 = .X
	}
	return 
}
If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
func ( ast.Expr) ast.Expr {
	if ,  := .(*ast.ParenExpr);  {
		 = (.X)
	}
	return 
}
checkExprOrType checks that x is an expression or a type (and not a raw type such as [...]T).
func ( *parser) ( ast.Expr) ast.Expr {
	switch t := unparen().(type) {
	case *ast.ParenExpr:
		panic("unreachable")
	case *ast.ArrayType:
		if ,  := .Len.(*ast.Ellipsis);  {
			.error(.Pos(), "expected array length, found '...'")
			 = &ast.BadExpr{From: .Pos(), To: .safePos(.End())}
		}
	}
all other nodes are expressions or types
	return 
}
If lhs is set and the result is an identifier, it is not resolved.
func ( *parser) ( bool) ast.Expr {
	if .trace {
		defer un(trace(, "PrimaryExpr"))
	}

	 := .parseOperand()
:
	for {
		switch .tok {
		case token.PERIOD:
			.next()
			if  {
				.resolve()
			}
			switch .tok {
			case token.IDENT:
				 = .parseSelector(.checkExprOrType())
			case token.LPAREN:
				 = .parseTypeAssertion(.checkExpr())
			default:
				 := .pos
				.errorExpected(, "selector or type assertion")
				.next() // make progress
				 := &ast.Ident{NamePos: , Name: "_"}
				 = &ast.SelectorExpr{X: , Sel: }
			}
		case token.LBRACK:
			if  {
				.resolve()
			}
			 = .parseIndexOrSlice(.checkExpr())
		case token.LPAREN:
			if  {
				.resolve()
			}
			 = .parseCallOrConversion(.checkExprOrType())
		case token.LBRACE:
			if isLiteralType() && (.exprLev >= 0 || !isTypeName()) {
				if  {
					.resolve()
				}
				 = .parseLiteralValue()
			} else {
				break 
			}
		default:
			break 
		}
		 = false // no need to try to resolve again
	}

	return 
}
If lhs is set and the result is an identifier, it is not resolved.
func ( *parser) ( bool) ast.Expr {
	if .trace {
		defer un(trace(, "UnaryExpr"))
	}

	switch .tok {
	case token.ADD, token.SUB, token.NOT, token.XOR, token.AND:
		,  := .pos, .tok
		.next()
		 := .(false)
		return &ast.UnaryExpr{OpPos: , Op: , X: .checkExpr()}

channel type or receive expression
		 := .pos
		.next()
If the next token is token.CHAN we still don't know if it is a channel type or a receive operation - we only know once we have found the end of the unary expression. There are two cases: <- type => (<-type) must be channel type <- expr => <-(expr) is a receive from an expression In the first case, the arrow must be re-associated with the channel type parsed already: <- (chan type) => (<-chan type) <- (chan<- type) => (<-chan (<-type))

		 := .(false)
determine which case we have
(<-type)
re-associate position info and <-
			 := ast.SEND
			for  &&  == ast.SEND {
error: (<-type) is (<-(<-chan T))
					.errorExpected(.Arrow, "'chan'")
				}
				, .Begin, .Arrow = .Arrow, , 
				, .Dir = .Dir, ast.RECV
				,  = .Value.(*ast.ChanType)
			}
			if  == ast.SEND {
				.errorExpected(, "channel type")
			}

			return 
		}
<-(expr)
		return &ast.UnaryExpr{OpPos: , Op: token.ARROW, X: .checkExpr()}

pointer type or unary "*" expression
		 := .pos
		.next()
		 := .(false)
		return &ast.StarExpr{Star: , X: .checkExprOrType()}
	}

	return .parsePrimaryExpr()
}

func ( *parser) () (token.Token, int) {
	 := .tok
	if .inRhs &&  == token.ASSIGN {
		 = token.EQL
	}
	return , .Precedence()
}
If lhs is set and the result is an identifier, it is not resolved.
func ( *parser) ( bool,  int) ast.Expr {
	if .trace {
		defer un(trace(, "BinaryExpr"))
	}

	 := .parseUnaryExpr()
	for {
		,  := .tokPrec()
		if  <  {
			return 
		}
		 := .expect()
		if  {
			.resolve()
			 = false
		}
		 := .(false, +1)
		 = &ast.BinaryExpr{X: .checkExpr(), OpPos: , Op: , Y: .checkExpr()}
	}
}
If lhs is set and the result is an identifier, it is not resolved. The result may be a type or even a raw type ([...]int). Callers must check the result (using checkExpr or checkExprOrType), depending on context.
func ( *parser) ( bool) ast.Expr {
	if .trace {
		defer un(trace(, "Expression"))
	}

	return .parseBinaryExpr(, token.LowestPrec+1)
}

func ( *parser) () ast.Expr {
	 := .inRhs
	.inRhs = true
	 := .checkExpr(.parseExpr(false))
	.inRhs = 
	return 
}

func ( *parser) () ast.Expr {
	 := .inRhs
	.inRhs = true
	 := .checkExprOrType(.parseExpr(false))
	.inRhs = 
	return 
}
---------------------------------------------------------------------------- Statements
Parsing modes for parseSimpleStmt.
const (
	basic = iota
	labelOk
	rangeOk
)
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.
assignment statement, possibly part of a range clause
		,  := .pos, .tok
		.next()
		var  []ast.Expr
		 := false
		if  == rangeOk && .tok == token.RANGE && ( == token.DEFINE ||  == token.ASSIGN) {
			 := .pos
			.next()
			 = []ast.Expr{&ast.UnaryExpr{OpPos: , Op: token.RANGE, X: .parseRhs()}}
			 = true
		} else {
			 = .parseRhsList()
		}
		 := &ast.AssignStmt{Lhs: , TokPos: , Tok: , Rhs: }
		if  == token.DEFINE {
			.shortVarDecl(, )
		}
		return , 
	}

	if len() > 1 {
continue with first expression
	}

	switch .tok {
labeled statement
		 := .pos
		.next()
Go spec: The scope of a label is the body of the function in which it is declared and excludes the body of any nested function.
			 := &ast.LabeledStmt{Label: , Colon: , Stmt: .parseStmt()}
			.declare(, nil, .labelScope, ast.Lbl, )
			return , false
The label declaration typically starts at x[0].Pos(), but the label declaration may be erroneous due to a token after that position (and before the ':'). If SpuriousErrors is not set, the (only) error reported for the line is the illegal label error instead of the token before the ':' that caused the problem. Thus, use the (latest) colon position for error reporting.
		.error(, "illegal label declaration")
		return &ast.BadStmt{From: [0].Pos(), To:  + 1}, false

send statement
		 := .pos
		.next()
		 := .parseRhs()
		return &ast.SendStmt{Chan: [0], Arrow: , Value: }, false

increment or decrement
		 := &ast.IncDecStmt{X: [0], TokPos: .pos, Tok: .tok}
		.next()
		return , false
	}
expression
	return &ast.ExprStmt{X: [0]}, false
}

func ( *parser) ( string) *ast.CallExpr {
	 := .parseRhsOrType() // could be a conversion: (some type)(x)
	if ,  := .(*ast.CallExpr);  {
		return 
	}
only report error if it's a new one
		.error(.safePos(.End()), fmt.Sprintf("function must be invoked in %s statement", ))
	}
	return nil
}

func ( *parser) () ast.Stmt {
	if .trace {
		defer un(trace(, "GoStmt"))
	}

	 := .expect(token.GO)
	 := .parseCallExpr("go")
	.expectSemi()
	if  == nil {
		return &ast.BadStmt{From: , To:  + 2} // len("go")
	}

	return &ast.GoStmt{Go: , Call: }
}

func ( *parser) () ast.Stmt {
	if .trace {
		defer un(trace(, "DeferStmt"))
	}

	 := .expect(token.DEFER)
	 := .parseCallExpr("defer")
	.expectSemi()
	if  == nil {
		return &ast.BadStmt{From: , To:  + 5} // len("defer")
	}

	return &ast.DeferStmt{Defer: , Call: }
}

func ( *parser) () *ast.ReturnStmt {
	if .trace {
		defer un(trace(, "ReturnStmt"))
	}

	 := .pos
	.expect(token.RETURN)
	var  []ast.Expr
	if .tok != token.SEMICOLON && .tok != token.RBRACE {
		 = .parseRhsList()
	}
	.expectSemi()

	return &ast.ReturnStmt{Return: , Results: }
}

func ( *parser) ( token.Token) *ast.BranchStmt {
	if .trace {
		defer un(trace(, "BranchStmt"))
	}

	 := .expect()
	var  *ast.Ident
	if  != token.FALLTHROUGH && .tok == token.IDENT {
add to list of unresolved targets
		 := len(.targetStack) - 1
		.targetStack[] = append(.targetStack[], )
	}
	.expectSemi()

	return &ast.BranchStmt{TokPos: , Tok: , Label: }
}

func ( *parser) ( ast.Stmt,  string) ast.Expr {
	if  == nil {
		return nil
	}
	if ,  := .(*ast.ExprStmt);  {
		return .checkExpr(.X)
	}
	 := "simple statement"
	if ,  := .(*ast.AssignStmt);  {
		 = "assignment"
	}
	.error(.Pos(), fmt.Sprintf("expected %s, found %s (missing parentheses around composite literal?)", , ))
	return &ast.BadExpr{From: .Pos(), To: .safePos(.End())}
}
parseIfHeader is an adjusted version of parser.header in cmd/compile/internal/syntax/parser.go, which has been tuned for better error handling.
func ( *parser) () ( ast.Stmt,  ast.Expr) {
	if .tok == token.LBRACE {
		.error(.pos, "missing condition in if statement")
		 = &ast.BadExpr{From: .pos, To: .pos}
		return
p.tok != token.LBRACE

	 := .exprLev
	.exprLev = -1

accept potential variable declaration but complain
		if .tok == token.VAR {
			.next()
			.error(.pos, fmt.Sprintf("var declaration not allowed in 'IF' initializer"))
		}
		, _ = .parseSimpleStmt(basic)
	}

	var  ast.Stmt
	var  struct {
		 token.Pos
		 string // ";" or "\n"; valid if pos.IsValid()
	}
	if .tok != token.LBRACE {
		if .tok == token.SEMICOLON {
			. = .pos
			. = .lit
			.next()
		} else {
			.expect(token.SEMICOLON)
		}
		if .tok != token.LBRACE {
			, _ = .parseSimpleStmt(basic)
		}
	} else {
		 = 
		 = nil
	}

	if  != nil {
		 = .makeExpr(, "boolean expression")
	} else if ..IsValid() {
		if . == "\n" {
			.error(., "unexpected newline, expecting { after if clause")
		} else {
			.error(., "missing condition in if statement")
		}
	}
make sure we have a valid AST
	if  == nil {
		 = &ast.BadExpr{From: .pos, To: .pos}
	}

	.exprLev = 
	return
}

func ( *parser) () *ast.IfStmt {
	if .trace {
		defer un(trace(, "IfStmt"))
	}

	 := .expect(token.IF)
	.openScope()
	defer .closeScope()

	,  := .parseIfHeader()
	 := .parseBlockStmt()

	var  ast.Stmt
	if .tok == token.ELSE {
		.next()
		switch .tok {
		case token.IF:
			 = .()
		case token.LBRACE:
			 = .parseBlockStmt()
			.expectSemi()
		default:
			.errorExpected(.pos, "if statement or block")
			 = &ast.BadStmt{From: .pos, To: .pos}
		}
	} else {
		.expectSemi()
	}

	return &ast.IfStmt{If: , Init: , Cond: , Body: , Else: }
}

func ( *parser) () ( []ast.Expr) {
	if .trace {
		defer un(trace(, "TypeList"))
	}

	 = append(, .parseType())
	for .tok == token.COMMA {
		.next()
		 = append(, .parseType())
	}

	return
}

func ( *parser) ( bool) *ast.CaseClause {
	if .trace {
		defer un(trace(, "CaseClause"))
	}

	 := .pos
	var  []ast.Expr
	if .tok == token.CASE {
		.next()
		if  {
			 = .parseTypeList()
		} else {
			 = .parseRhsList()
		}
	} else {
		.expect(token.DEFAULT)
	}

	 := .expect(token.COLON)
	.openScope()
	 := .parseStmtList()
	.closeScope()

	return &ast.CaseClause{Case: , List: , Colon: , Body: }
}

func ( ast.Expr) bool {
	,  := .(*ast.TypeAssertExpr)
	return  && .Type == nil
}

func ( *parser) ( ast.Stmt) bool {
	switch t := .(type) {
x.(type)
		return isTypeSwitchAssert(.X)
v := x.(type)
		if len(.Lhs) == 1 && len(.Rhs) == 1 && isTypeSwitchAssert(.Rhs[0]) {
			switch .Tok {
permit v = x.(type) but complain
				.error(.TokPos, "expected ':=', found '='")
				fallthrough
			case token.DEFINE:
				return true
			}
		}
	}
	return false
}

func ( *parser) () ast.Stmt {
	if .trace {
		defer un(trace(, "SwitchStmt"))
	}

	 := .expect(token.SWITCH)
	.openScope()
	defer .closeScope()

	var ,  ast.Stmt
	if .tok != token.LBRACE {
		 := .exprLev
		.exprLev = -1
		if .tok != token.SEMICOLON {
			, _ = .parseSimpleStmt(basic)
		}
		if .tok == token.SEMICOLON {
			.next()
			 = 
			 = nil
A TypeSwitchGuard may declare a variable in addition to the variable declared in the initial SimpleStmt. Introduce extra scope to avoid redeclaration errors: switch t := 0; t := x.(T) { ... } (this code is not valid Go because the first t cannot be accessed and thus is never used, the extra scope is needed for the correct error message). If we don't have a type switch, s2 must be an expression. Having the extra nested but empty scope won't affect it.
				.openScope()
				defer .closeScope()
				, _ = .parseSimpleStmt(basic)
			}
		}
		.exprLev = 
	}

	 := .isTypeSwitchGuard()
	 := .expect(token.LBRACE)
	var  []ast.Stmt
	for .tok == token.CASE || .tok == token.DEFAULT {
		 = append(, .parseCaseClause())
	}
	 := .expect(token.RBRACE)
	.expectSemi()
	 := &ast.BlockStmt{Lbrace: , List: , Rbrace: }

	if  {
		return &ast.TypeSwitchStmt{Switch: , Init: , Assign: , Body: }
	}

	return &ast.SwitchStmt{Switch: , Init: , Tag: .makeExpr(, "switch expression"), Body: }
}

func ( *parser) () *ast.CommClause {
	if .trace {
		defer un(trace(, "CommClause"))
	}

	.openScope()
	 := .pos
	var  ast.Stmt
	if .tok == token.CASE {
		.next()
		 := .parseLhsList()
SendStmt
			if len() > 1 {
continue with first expression
			}
			 := .pos
			.next()
			 := .parseRhs()
			 = &ast.SendStmt{Chan: [0], Arrow: , Value: }
RecvStmt
RecvStmt with assignment
				if len() > 2 {
continue with first two expressions
					 = [0:2]
				}
				 := .pos
				.next()
				 := .parseRhs()
				 := &ast.AssignStmt{Lhs: , TokPos: , Tok: , Rhs: []ast.Expr{}}
				if  == token.DEFINE {
					.shortVarDecl(, )
				}
				 = 
lhs must be single receive operation
				if len() > 1 {
continue with first expression
				}
				 = &ast.ExprStmt{X: [0]}
			}
		}
	} else {
		.expect(token.DEFAULT)
	}

	 := .expect(token.COLON)
	 := .parseStmtList()
	.closeScope()

	return &ast.CommClause{Case: , Comm: , Colon: , Body: }
}

func ( *parser) () *ast.SelectStmt {
	if .trace {
		defer un(trace(, "SelectStmt"))
	}

	 := .expect(token.SELECT)
	 := .expect(token.LBRACE)
	var  []ast.Stmt
	for .tok == token.CASE || .tok == token.DEFAULT {
		 = append(, .parseCommClause())
	}
	 := .expect(token.RBRACE)
	.expectSemi()
	 := &ast.BlockStmt{Lbrace: , List: , Rbrace: }

	return &ast.SelectStmt{Select: , Body: }
}

func ( *parser) () ast.Stmt {
	if .trace {
		defer un(trace(, "ForStmt"))
	}

	 := .expect(token.FOR)
	.openScope()
	defer .closeScope()

	var , ,  ast.Stmt
	var  bool
	if .tok != token.LBRACE {
		 := .exprLev
		.exprLev = -1
		if .tok != token.SEMICOLON {
"for range x" (nil lhs in assignment)
				 := .pos
				.next()
				 := []ast.Expr{&ast.UnaryExpr{OpPos: , Op: token.RANGE, X: .parseRhs()}}
				 = &ast.AssignStmt{Rhs: }
				 = true
			} else {
				,  = .parseSimpleStmt(rangeOk)
			}
		}
		if ! && .tok == token.SEMICOLON {
			.next()
			 = 
			 = nil
			if .tok != token.SEMICOLON {
				, _ = .parseSimpleStmt(basic)
			}
			.expectSemi()
			if .tok != token.LBRACE {
				, _ = .parseSimpleStmt(basic)
			}
		}
		.exprLev = 
	}

	 := .parseBlockStmt()
	.expectSemi()

	if  {
check lhs
		var ,  ast.Expr
		switch len(.Lhs) {
nothing to do
		case 1:
			 = .Lhs[0]
		case 2:
			,  = .Lhs[0], .Lhs[1]
		default:
			.errorExpected(.Lhs[len(.Lhs)-1].Pos(), "at most 2 expressions")
			return &ast.BadStmt{From: , To: .safePos(.End())}
parseSimpleStmt returned a right-hand side that is a single unary expression of the form "range x"
		 := .Rhs[0].(*ast.UnaryExpr).X
		return &ast.RangeStmt{
			For:    ,
			Key:    ,
			Value:  ,
			TokPos: .TokPos,
			Tok:    .Tok,
			X:      ,
			Body:   ,
		}
	}
regular for statement
	return &ast.ForStmt{
		For:  ,
		Init: ,
		Cond: .makeExpr(, "boolean or range expression"),
		Post: ,
		Body: ,
	}
}

func ( *parser) () ( ast.Stmt) {
	if .trace {
		defer un(trace(, "Statement"))
	}

	switch .tok {
	case token.CONST, token.TYPE, token.VAR:
		 = &ast.DeclStmt{Decl: .parseDecl(stmtStart)}
tokens that may start an expression
because of the required look-ahead, labeled statements are parsed by parseSimpleStmt - don't expect a semicolon after them
		if ,  := .(*ast.LabeledStmt); ! {
			.expectSemi()
		}
	case token.GO:
		 = .parseGoStmt()
	case token.DEFER:
		 = .parseDeferStmt()
	case token.RETURN:
		 = .parseReturnStmt()
	case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
		 = .parseBranchStmt(.tok)
	case token.LBRACE:
		 = .parseBlockStmt()
		.expectSemi()
	case token.IF:
		 = .parseIfStmt()
	case token.SWITCH:
		 = .parseSwitchStmt()
	case token.SELECT:
		 = .parseSelectStmt()
	case token.FOR:
		 = .parseForStmt()
Is it ever possible to have an implicit semicolon producing an empty statement in a valid program? (handle correctly anyway)
		 = &ast.EmptyStmt{Semicolon: .pos, Implicit: .lit == "\n"}
		.next()
a semicolon may be omitted before a closing "}"
no statement found
		 := .pos
		.errorExpected(, "statement")
		.advance(stmtStart)
		 = &ast.BadStmt{From: , To: .pos}
	}

	return
}
---------------------------------------------------------------------------- Declarations

type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec

func ( string) bool {
	const  = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
	,  := strconv.Unquote() // go/scanner returns a legal string literal
	for ,  := range  {
		if !unicode.IsGraphic() || unicode.IsSpace() || strings.ContainsRune(, ) {
			return false
		}
	}
	return  != ""
}

func ( *parser) ( *ast.CommentGroup,  token.Token,  int) ast.Spec {
	if .trace {
		defer un(trace(, "ImportSpec"))
	}

	var  *ast.Ident
	switch .tok {
	case token.PERIOD:
		 = &ast.Ident{NamePos: .pos, Name: "."}
		.next()
	case token.IDENT:
		 = .parseIdent()
	}

	 := .pos
	var  string
	if .tok == token.STRING {
		 = .lit
		if !isValidImport() {
			.error(, "invalid import path: "+)
		}
		.next()
	} else {
		.expect(token.STRING) // use expect() error handling
	}
	.expectSemi() // call before accessing p.linecomment
collect imports
	 := &ast.ImportSpec{
		Doc:     ,
		Name:    ,
		Path:    &ast.BasicLit{ValuePos: , Kind: token.STRING, Value: },
		Comment: .lineComment,
	}
	.imports = append(.imports, )

	return 
}

func ( *parser) ( *ast.CommentGroup,  token.Token,  int) ast.Spec {
	if .trace {
		defer un(trace(, .String()+"Spec"))
	}

	 := .pos
	 := .parseIdentList()
	 := .tryType()
always permit optional initialization for more tolerant parsing
	if .tok == token.ASSIGN {
		.next()
		 = .parseRhsList()
	}
	.expectSemi() // call before accessing p.linecomment

	switch  {
	case token.VAR:
		if  == nil &&  == nil {
			.error(, "missing variable type or initialization")
		}
	case token.CONST:
		if  == nil && ( == 0 ||  != nil) {
			.error(, "missing constant value")
		}
	}
Go spec: The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec and ends at the end of the innermost containing block. (Global identifiers are resolved in a separate phase after parsing.)
	 := &ast.ValueSpec{
		Doc:     ,
		Names:   ,
		Type:    ,
		Values:  ,
		Comment: .lineComment,
	}
	 := ast.Con
	if  == token.VAR {
		 = ast.Var
	}
	.declare(, , .topScope, , ...)

	return 
}

func ( *parser) ( *ast.CommentGroup,  token.Token,  int) ast.Spec {
	if .trace {
		defer un(trace(, "TypeSpec"))
	}

	 := .parseIdent()
Go spec: The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block. (Global identifiers are resolved in a separate phase after parsing.)
	 := &ast.TypeSpec{Doc: , Name: }
	.declare(, nil, .topScope, ast.Typ, )
	if .tok == token.ASSIGN {
		.Assign = .pos
		.next()
	}
	.Type = .parseType()
	.expectSemi() // call before accessing p.linecomment
	.Comment = .lineComment

	return 
}

func ( *parser) ( token.Token,  parseSpecFunction) *ast.GenDecl {
	if .trace {
		defer un(trace(, "GenDecl("+.String()+")"))
	}

	 := .leadComment
	 := .expect()
	var ,  token.Pos
	var  []ast.Spec
	if .tok == token.LPAREN {
		 = .pos
		.next()
		for  := 0; .tok != token.RPAREN && .tok != token.EOF; ++ {
			 = append(, (.leadComment, , ))
		}
		 = .expect(token.RPAREN)
		.expectSemi()
	} else {
		 = append(, (nil, , 0))
	}

	return &ast.GenDecl{
		Doc:    ,
		TokPos: ,
		Tok:    ,
		Lparen: ,
		Specs:  ,
		Rparen: ,
	}
}

func ( *parser) () *ast.FuncDecl {
	if .trace {
		defer un(trace(, "FunctionDecl"))
	}

	 := .leadComment
	 := .expect(token.FUNC)
	 := ast.NewScope(.topScope) // function scope

	var  *ast.FieldList
	if .tok == token.LPAREN {
		 = .parseParameters(, false)
	}

	 := .parseIdent()

	,  := .parseSignature()

	var  *ast.BlockStmt
	if .tok == token.LBRACE {
		 = .parseBody()
		.expectSemi()
	} else if .tok == token.SEMICOLON {
		.next()
opening { of function declaration on next line
			.error(.pos, "unexpected semicolon or newline before {")
			 = .parseBody()
			.expectSemi()
		}
	} else {
		.expectSemi()
	}

	 := &ast.FuncDecl{
		Doc:  ,
		Recv: ,
		Name: ,
		Type: &ast.FuncType{
			Func:    ,
			Params:  ,
			Results: ,
		},
		Body: ,
	}
Go spec: The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block. init() functions cannot be referred to and there may be more than one - don't put them in the pkgScope
		if .Name != "init" {
			.declare(, nil, .pkgScope, ast.Fun, )
		}
	}

	return 
}

func ( *parser) ( map[token.Token]bool) ast.Decl {
	if .trace {
		defer un(trace(, "Declaration"))
	}

	var  parseSpecFunction
	switch .tok {
	case token.CONST, token.VAR:
		 = .parseValueSpec

	case token.TYPE:
		 = .parseTypeSpec

	case token.FUNC:
		return .parseFuncDecl()

	default:
		 := .pos
		.errorExpected(, "declaration")
		.advance()
		return &ast.BadDecl{From: , To: .pos}
	}

	return .parseGenDecl(.tok, )
}
---------------------------------------------------------------------------- Source files

func ( *parser) () *ast.File {
	if .trace {
		defer un(trace(, "File"))
	}
Don't bother parsing the rest if we had errors scanning the first token. Likely not a Go source file at all.
	if .errors.Len() != 0 {
		return nil
	}
package clause
	 := .leadComment
Go spec: The package clause is not a declaration; the package name does not appear in any scope.
	 := .parseIdent()
	if .Name == "_" && .mode&DeclarationErrors != 0 {
		.error(.pos, "invalid package name _")
	}
	.expectSemi()
Don't bother parsing the rest if we had errors parsing the package clause. Likely not a Go source file at all.
	if .errors.Len() != 0 {
		return nil
	}

	.openScope()
	.pkgScope = .topScope
	var  []ast.Decl
import decls
		for .tok == token.IMPORT {
			 = append(, .parseGenDecl(token.IMPORT, .parseImportSpec))
		}

rest of package body
			for .tok != token.EOF {
				 = append(, .parseDecl(declStart))
			}
		}
	}
	.closeScope()
	assert(.topScope == nil, "unbalanced scopes")
	assert(.labelScope == nil, "unbalanced label scopes")
resolve global identifiers within the same file
	 := 0
i <= index for current ident
		assert(.Obj == unresolved, "object already resolved")
		.Obj = .pkgScope.Lookup(.Name) // also removes unresolved sentinel
		if .Obj == nil {
			.unresolved[] = 
			++
		}
	}

	return &ast.File{
		Doc:        ,
		Package:    ,
		Name:       ,
		Decls:      ,
		Scope:      .pkgScope,
		Imports:    .imports,
		Unresolved: .unresolved[0:],
		Comments:   .comments,
	}