package  parserimport  (	"fmt" 	"go/ast" 	"go/build/constraint" 	"go/scanner" 	"go/token" 	"strings" )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 }func  (p  *parser ) init (file  *token .File , src  []byte , mode  Mode ) {	p .file  = file 	eh  := func (pos  token .Position , msg  string ) { p .errors .Add (pos , msg ) }	p .scanner .Init (p .file , src , eh , scanner .ScanComments )	p .top  = true 	p .mode  = mode 	p .trace  = mode &Trace  != 0  	p .next ()}func  (p  *parser ) printTrace (a  ...any ) {	const  dots  = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " 	const  n  = len (dots )	pos  := p .file .Position (p .pos )	fmt .Printf ("%5d:%3d: " , pos .Line , pos .Column )	i  := 2  * p .indent 	for  i  > n  {		fmt .Print (dots )		i  -= n 	}		fmt .Print (dots [0 :i ])	fmt .Println (a ...)}func  trace(p  *parser , msg  string ) *parser  {	p .printTrace (msg , "(" )	p .indent ++	return  p }func  un(p  *parser ) {	p .indent --	p .printTrace (")" )}const  maxNestLev int  = 1e5 func  incNestLev(p  *parser ) *parser  {	p .nestLev ++	if  p .nestLev  > maxNestLev  {		p .error (p .pos , "exceeded max nesting depth" )		panic (bailout {})	}	return  p }func  decNestLev(p  *parser ) {	p .nestLev --}func  (p  *parser ) next0 () {		if  p .trace  && p .pos .IsValid () {		s  := p .tok .String ()		switch  {		case  p .tok .IsLiteral ():			p .printTrace (s , p .lit )		case  p .tok .IsOperator (), p .tok .IsKeyword ():			p .printTrace ("\""  + s  + "\"" )		default :			p .printTrace (s )		}	}	for  {		p .pos , p .tok , p .lit  = p .scanner .Scan ()		if  p .tok  == token .COMMENT  {			if  p .top  && strings .HasPrefix (p .lit , "//go:build" ) {				if  x , err  := constraint .Parse (p .lit ); err  == nil  {					p .goVersion  = constraint .GoVersion (x )				}			}			if  p .mode &ParseComments  == 0  {				continue 			}		} else  {						p .top  = false 		}		break 	}}func  (p  *parser ) lineFor (pos  token .Pos ) int  {	return  p .file .PositionFor (pos , false ).Line }func  (p  *parser ) consumeComment () (comment  *ast .Comment , endline  int ) {		endline  = p .lineFor (p .pos )	if  p .lit [1 ] == '*'  {				for  i  := 0 ; i  < len (p .lit ); i ++ {			if  p .lit [i ] == '\n'  {				endline ++			}		}	}	comment  = &ast .Comment {Slash : p .pos , Text : p .lit }	p .next0 ()	return }func  (p  *parser ) consumeCommentGroup (n  int ) (comments  *ast .CommentGroup , endline  int ) {	var  list  []*ast .Comment 	endline  = p .lineFor (p .pos )	for  p .tok  == token .COMMENT  && p .lineFor (p .pos ) <= endline +n  {		var  comment  *ast .Comment 		comment , endline  = p .consumeComment ()		list  = append (list , comment )	}		comments  = &ast .CommentGroup {List : list }	p .comments  = append (p .comments , comments )	return }func  (p  *parser ) next () {	p .leadComment  = nil 	p .lineComment  = nil 	prev  := p .pos 	p .next0 ()	if  p .tok  == token .COMMENT  {		var  comment  *ast .CommentGroup 		var  endline  int 		if  p .lineFor (p .pos ) == p .lineFor (prev ) {						comment , endline  = p .consumeCommentGroup (0 )			if  p .lineFor (p .pos ) != endline  || p .tok  == token .SEMICOLON  || p .tok  == token .EOF  {								p .lineComment  = comment 			}		}				endline  = -1 		for  p .tok  == token .COMMENT  {			comment , endline  = p .consumeCommentGroup (1 )		}		if  endline +1  == p .lineFor (p .pos ) {						p .leadComment  = comment 		}	}}type  bailout struct  {	pos token .Pos 	msg string }func  (p  *parser ) error (pos  token .Pos , msg  string ) {	if  p .trace  {		defer  un (trace (p , "error: " +msg ))	}	epos  := p .file .Position (pos )		if  p .mode &AllErrors  == 0  {		n  := len (p .errors )		if  n  > 0  && p .errors [n -1 ].Pos .Line  == epos .Line  {			return  		}		if  n  > 10  {			panic (bailout {})		}	}	p .errors .Add (epos , msg )}func  (p  *parser ) errorExpected (pos  token .Pos , msg  string ) {	msg  = "expected "  + msg 	if  pos  == p .pos  {				switch  {		case  p .tok  == token .SEMICOLON  && p .lit  == "\n" :			msg  += ", found newline" 		case  p .tok .IsLiteral ():						msg  += ", found "  + p .lit 		default :			msg  += ", found '"  + p .tok .String () + "'" 		}	}	p .error (pos , msg )}func  (p  *parser ) expect (tok  token .Token ) token .Pos  {	pos  := p .pos 	if  p .tok  != tok  {		p .errorExpected (pos , "'" +tok .String ()+"'" )	}	p .next () 	return  pos }func  (p  *parser ) expect2 (tok  token .Token ) (pos  token .Pos ) {	if  p .tok  == tok  {		pos  = p .pos 	} else  {		p .errorExpected (p .pos , "'" +tok .String ()+"'" )	}	p .next () 	return }func  (p  *parser ) expectClosing (tok  token .Token , context  string ) token .Pos  {	if  p .tok  != tok  && p .tok  == token .SEMICOLON  && p .lit  == "\n"  {		p .error (p .pos , "missing ',' before newline in " +context )		p .next ()	}	return  p .expect (tok )}func  (p  *parser ) expectSemi () (comment  *ast .CommentGroup ) {		if  p .tok  != token .RPAREN  && p .tok  != token .RBRACE  {		switch  p .tok  {		case  token .COMMA :						p .errorExpected (p .pos , "';'" )			fallthrough 		case  token .SEMICOLON :			if  p .lit  == ";"  {								p .next ()				comment  = p .lineComment  			} else  {								comment  = p .lineComment  				p .next ()			}			return  comment 		default :			p .errorExpected (p .pos , "';'" )			p .advance (stmtStart )		}	}	return  nil }func  (p  *parser ) atComma (context  string , follow  token .Token ) bool  {	if  p .tok  == token .COMMA  {		return  true 	}	if  p .tok  != follow  {		msg  := "missing ','" 		if  p .tok  == token .SEMICOLON  && p .lit  == "\n"  {			msg  += " before newline" 		}		p .error (p .pos , msg +" in " +context )		return  true  	}	return  false }func  assert(cond  bool , msg  string ) {	if  !cond  {		panic ("go/parser internal error: "  + msg )	}}func  (p  *parser ) advance (to  map [token .Token ]bool ) {	for  ; p .tok  != token .EOF ; p .next () {		if  to [p .tok ] {						if  p .pos  == p .syncPos  && p .syncCnt  < 10  {				p .syncCnt ++				return 			}			if  p .pos  > p .syncPos  {				p .syncPos  = p .pos 				p .syncCnt  = 0 				return 			}					}	}}var  stmtStart = map [token .Token ]bool {	token .BREAK :       true ,	token .CONST :       true ,	token .CONTINUE :    true ,	token .DEFER :       true ,	token .FALLTHROUGH : true ,	token .FOR :         true ,	token .GO :          true ,	token .GOTO :        true ,	token .IF :          true ,	token .RETURN :      true ,	token .SELECT :      true ,	token .SWITCH :      true ,	token .TYPE :        true ,	token .VAR :         true ,}var  declStart = map [token .Token ]bool {	token .IMPORT : true ,	token .CONST :  true ,	token .TYPE :   true ,	token .VAR :    true ,}var  exprEnd = map [token .Token ]bool {	token .COMMA :     true ,	token .COLON :     true ,	token .SEMICOLON : true ,	token .RPAREN :    true ,	token .RBRACK :    true ,	token .RBRACE :    true ,}func  (p  *parser ) safePos (pos  token .Pos ) (res  token .Pos ) {	defer  func () {		if  recover () != nil  {			res  = token .Pos (p .file .Base () + p .file .Size ()) 		}	}()	_ = p .file .Offset (pos ) 	return  pos }func  (p  *parser ) parseIdent () *ast .Ident  {	pos  := p .pos 	name  := "_" 	if  p .tok  == token .IDENT  {		name  = p .lit 		p .next ()	} else  {		p .expect (token .IDENT ) 	}	return  &ast .Ident {NamePos : pos , Name : name }}func  (p  *parser ) parseIdentList () (list  []*ast .Ident ) {	if  p .trace  {		defer  un (trace (p , "IdentList" ))	}	list  = append (list , p .parseIdent ())	for  p .tok  == token .COMMA  {		p .next ()		list  = append (list , p .parseIdent ())	}	return }func  (p  *parser ) parseExprList () (list  []ast .Expr ) {	if  p .trace  {		defer  un (trace (p , "ExpressionList" ))	}	list  = append (list , p .parseExpr ())	for  p .tok  == token .COMMA  {		p .next ()		list  = append (list , p .parseExpr ())	}	return }func  (p  *parser ) parseList (inRhs  bool ) []ast .Expr  {	old  := p .inRhs 	p .inRhs  = inRhs 	list  := p .parseExprList ()	p .inRhs  = old 	return  list }func  (p  *parser ) parseType () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Type" ))	}	typ  := p .tryIdentOrType ()	if  typ  == nil  {		pos  := p .pos 		p .errorExpected (pos , "type" )		p .advance (exprEnd )		return  &ast .BadExpr {From : pos , To : p .pos }	}	return  typ }func  (p  *parser ) parseQualifiedIdent (ident  *ast .Ident ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "QualifiedIdent" ))	}	typ  := p .parseTypeName (ident )	if  p .tok  == token .LBRACK  {		typ  = p .parseTypeInstance (typ )	}	return  typ }func  (p  *parser ) parseTypeName (ident  *ast .Ident ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "TypeName" ))	}	if  ident  == nil  {		ident  = p .parseIdent ()	}	if  p .tok  == token .PERIOD  {				p .next ()		sel  := p .parseIdent ()		return  &ast .SelectorExpr {X : ident , Sel : sel }	}	return  ident }func  (p  *parser ) parseArrayType (lbrack  token .Pos , len  ast .Expr ) *ast .ArrayType  {	if  p .trace  {		defer  un (trace (p , "ArrayType" ))	}	if  len  == nil  {		p .exprLev ++				if  p .tok  == token .ELLIPSIS  {			len  = &ast .Ellipsis {Ellipsis : p .pos }			p .next ()		} else  if  p .tok  != token .RBRACK  {			len  = p .parseRhs ()		}		p .exprLev --	}	if  p .tok  == token .COMMA  {				p .error (p .pos , "unexpected comma; expecting ]" )		p .next ()	}	p .expect (token .RBRACK )	elt  := p .parseType ()	return  &ast .ArrayType {Lbrack : lbrack , Len : len , Elt : elt }}func  (p  *parser ) parseArrayFieldOrTypeInstance (x  *ast .Ident ) (*ast .Ident , ast .Expr ) {	if  p .trace  {		defer  un (trace (p , "ArrayFieldOrTypeInstance" ))	}	lbrack  := p .expect (token .LBRACK )	trailingComma  := token .NoPos  	var  args  []ast .Expr 	if  p .tok  != token .RBRACK  {		p .exprLev ++		args  = append (args , p .parseRhs ())		for  p .tok  == token .COMMA  {			comma  := p .pos 			p .next ()			if  p .tok  == token .RBRACK  {				trailingComma  = comma 				break 			}			args  = append (args , p .parseRhs ())		}		p .exprLev --	}	rbrack  := p .expect (token .RBRACK )	if  len (args ) == 0  {				elt  := p .parseType ()		return  x , &ast .ArrayType {Lbrack : lbrack , Elt : elt }	}		if  len (args ) == 1  {		elt  := p .tryIdentOrType ()		if  elt  != nil  {						if  trailingComma .IsValid () {								p .error (trailingComma , "unexpected comma; expecting ]" )			}			return  x , &ast .ArrayType {Lbrack : lbrack , Len : args [0 ], Elt : elt }		}	}		return  nil , packIndexExpr (x , lbrack , args , rbrack )}func  (p  *parser ) parseFieldDecl () *ast .Field  {	if  p .trace  {		defer  un (trace (p , "FieldDecl" ))	}	doc  := p .leadComment 	var  names  []*ast .Ident 	var  typ  ast .Expr 	switch  p .tok  {	case  token .IDENT :		name  := p .parseIdent ()		if  p .tok  == token .PERIOD  || p .tok  == token .STRING  || p .tok  == token .SEMICOLON  || p .tok  == token .RBRACE  {						typ  = name 			if  p .tok  == token .PERIOD  {				typ  = p .parseQualifiedIdent (name )			}		} else  {						names  = []*ast .Ident {name }			for  p .tok  == token .COMMA  {				p .next ()				names  = append (names , p .parseIdent ())			}						if  len (names ) == 1  && p .tok  == token .LBRACK  {				name , typ  = p .parseArrayFieldOrTypeInstance (name )				if  name  == nil  {					names  = nil 				}			} else  {								typ  = p .parseType ()			}		}	case  token .MUL :		star  := p .pos 		p .next ()		if  p .tok  == token .LPAREN  {						p .error (p .pos , "cannot parenthesize embedded type" )			p .next ()			typ  = p .parseQualifiedIdent (nil )						if  p .tok  == token .RPAREN  {				p .next ()			}		} else  {						typ  = p .parseQualifiedIdent (nil )		}		typ  = &ast .StarExpr {Star : star , X : typ }	case  token .LPAREN :		p .error (p .pos , "cannot parenthesize embedded type" )		p .next ()		if  p .tok  == token .MUL  {						star  := p .pos 			p .next ()			typ  = &ast .StarExpr {Star : star , X : p .parseQualifiedIdent (nil )}		} else  {						typ  = p .parseQualifiedIdent (nil )		}				if  p .tok  == token .RPAREN  {			p .next ()		}	default :		pos  := p .pos 		p .errorExpected (pos , "field name or embedded type" )		p .advance (exprEnd )		typ  = &ast .BadExpr {From : pos , To : p .pos }	}	var  tag  *ast .BasicLit 	if  p .tok  == token .STRING  {		tag  = &ast .BasicLit {ValuePos : p .pos , Kind : p .tok , Value : p .lit }		p .next ()	}	comment  := p .expectSemi ()	field  := &ast .Field {Doc : doc , Names : names , Type : typ , Tag : tag , Comment : comment }	return  field }func  (p  *parser ) parseStructType () *ast .StructType  {	if  p .trace  {		defer  un (trace (p , "StructType" ))	}	pos  := p .expect (token .STRUCT )	lbrace  := p .expect (token .LBRACE )	var  list  []*ast .Field 	for  p .tok  == token .IDENT  || p .tok  == token .MUL  || p .tok  == token .LPAREN  {				list  = append (list , p .parseFieldDecl ())	}	rbrace  := p .expect (token .RBRACE )	return  &ast .StructType {		Struct : pos ,		Fields : &ast .FieldList {			Opening : lbrace ,			List :    list ,			Closing : rbrace ,		},	}}func  (p  *parser ) parsePointerType () *ast .StarExpr  {	if  p .trace  {		defer  un (trace (p , "PointerType" ))	}	star  := p .expect (token .MUL )	base  := p .parseType ()	return  &ast .StarExpr {Star : star , X : base }}func  (p  *parser ) parseDotsType () *ast .Ellipsis  {	if  p .trace  {		defer  un (trace (p , "DotsType" ))	}	pos  := p .expect (token .ELLIPSIS )	elt  := p .parseType ()	return  &ast .Ellipsis {Ellipsis : pos , Elt : elt }}type  field struct  {	name *ast .Ident 	typ  ast .Expr }func  (p  *parser ) parseParamDecl (name  *ast .Ident , typeSetsOK  bool ) (f  field ) {		if  p .trace  {		defer  un (trace (p , "ParamDecl" ))	}	ptok  := p .tok 	if  name  != nil  {		p .tok  = token .IDENT  	} else  if  typeSetsOK  && p .tok  == token .TILDE  {				return  field {nil , p .embeddedElem (nil )}	}	switch  p .tok  {	case  token .IDENT :				if  name  != nil  {			f .name  = name 			p .tok  = ptok 		} else  {			f .name  = p .parseIdent ()		}		switch  p .tok  {		case  token .IDENT , token .MUL , token .ARROW , token .FUNC , token .CHAN , token .MAP , token .STRUCT , token .INTERFACE , token .LPAREN :						f .typ  = p .parseType ()		case  token .LBRACK :						f .name , f .typ  = p .parseArrayFieldOrTypeInstance (f .name )		case  token .ELLIPSIS :						f .typ  = p .parseDotsType ()			return  		case  token .PERIOD :						f .typ  = p .parseQualifiedIdent (f .name )			f .name  = nil 		case  token .TILDE :			if  typeSetsOK  {				f .typ  = p .embeddedElem (nil )				return 			}		case  token .OR :			if  typeSetsOK  {								f .typ  = p .embeddedElem (f .name )				f .name  = nil 				return 			}		}	case  token .MUL , token .ARROW , token .FUNC , token .LBRACK , token .CHAN , token .MAP , token .STRUCT , token .INTERFACE , token .LPAREN :				f .typ  = p .parseType ()	case  token .ELLIPSIS :				f .typ  = p .parseDotsType ()		return  	default :				p .errorExpected (p .pos , "')'" )		p .advance (exprEnd )	}		if  typeSetsOK  && p .tok  == token .OR  && f .typ  != nil  {		f .typ  = p .embeddedElem (f .typ )	}	return }func  (p  *parser ) parseParameterList (name0  *ast .Ident , typ0  ast .Expr , closing  token .Token , dddok  bool ) (params  []*ast .Field ) {	if  p .trace  {		defer  un (trace (p , "ParameterList" ))	}		tparams  := closing  == token .RBRACK 	pos0  := p .pos 	if  name0  != nil  {		pos0  = name0 .Pos ()	} else  if  typ0  != nil  {		pos0  = typ0 .Pos ()	}		var  list  []field 	var  named  int  	var  typed  int  	for  name0  != nil  || p .tok  != closing  && p .tok  != token .EOF  {		var  par  field 		if  typ0  != nil  {			if  tparams  {				typ0  = p .embeddedElem (typ0 )			}			par  = field {name0 , typ0 }		} else  {			par  = p .parseParamDecl (name0 , tparams )		}		name0  = nil  		typ0  = nil   		if  par .name  != nil  || par .typ  != nil  {			list  = append (list , par )			if  par .name  != nil  && par .typ  != nil  {				named ++			}			if  par .typ  != nil  {				typed ++			}		}		if  !p .atComma ("parameter list" , closing ) {			break 		}		p .next ()	}	if  len (list ) == 0  {		return  	}		if  named  == 0  {				for  i  := range  list  {			par  := &list [i ]			if  typ  := par .name ; typ  != nil  {				par .typ  = typ 				par .name  = nil 			}		}		if  tparams  {						var  errPos  token .Pos 			var  msg  string 			if  named  == typed   {				errPos  = p .pos  				msg  = "missing type constraint" 			} else  {				errPos  = pos0  				msg  = "missing type parameter name" 				if  len (list ) == 1  {					msg  += " or invalid array length" 				}			}			p .error (errPos , msg )		}	} else  if  named  != len (list ) {				var  errPos  token .Pos  		var  typ  ast .Expr      		for  i  := range  list  {			if  par  := &list [len (list )-i -1 ]; par .typ  != nil  {				typ  = par .typ 				if  par .name  == nil  {					errPos  = typ .Pos ()					n  := ast .NewIdent ("_" )					n .NamePos  = errPos  					par .name  = n 				}			} else  if  typ  != nil  {				par .typ  = typ 			} else  {								errPos  = par .name .Pos ()				par .typ  = &ast .BadExpr {From : errPos , To : p .pos }			}		}		if  errPos .IsValid () {						var  msg  string 			if  named  == typed  {				errPos  = p .pos  				if  tparams  {					msg  = "missing type constraint" 				} else  {					msg  = "missing parameter type" 				}			} else  {				if  tparams  {					msg  = "missing type parameter name" 										if  len (list ) == 1  {						msg  += " or invalid array length" 					}				} else  {					msg  = "missing parameter name" 				}			}			p .error (errPos , msg )		}	}		first  := true  	for  i , _  := range  list  {		f  := &list [i ]		if  t , _  := f .typ .(*ast .Ellipsis ); t  != nil  && (!dddok  || i +1  < len (list )) {			if  first  {				first  = false 				if  dddok  {					p .error (t .Ellipsis , "can only use ... with final parameter" )				} else  {					p .error (t .Ellipsis , "invalid use of ..." )				}			}						f .typ  = &ast .BadExpr {From : t .Pos (), To : t .End ()}		}	}		if  named  == 0  {				for  _ , par  := range  list  {			assert (par .typ  != nil , "nil type in unnamed parameter list" )			params  = append (params , &ast .Field {Type : par .typ })		}		return 	}		var  names  []*ast .Ident 	var  typ  ast .Expr 	addParams  := func () {		assert (typ  != nil , "nil type in named parameter list" )		field  := &ast .Field {Names : names , Type : typ }		params  = append (params , field )		names  = nil 	}	for  _ , par  := range  list  {		if  par .typ  != typ  {			if  len (names ) > 0  {				addParams ()			}			typ  = par .typ 		}		names  = append (names , par .name )	}	if  len (names ) > 0  {		addParams ()	}	return }func  (p  *parser ) parseTypeParameters () *ast .FieldList  {	if  p .trace  {		defer  un (trace (p , "TypeParameters" ))	}	lbrack  := p .expect (token .LBRACK )	var  list  []*ast .Field 	if  p .tok  != token .RBRACK  {		list  = p .parseParameterList (nil , nil , token .RBRACK , false )	}	rbrack  := p .expect (token .RBRACK )	if  len (list ) == 0  {		p .error (rbrack , "empty type parameter list" )		return  nil  	}	return  &ast .FieldList {Opening : lbrack , List : list , Closing : rbrack }}func  (p  *parser ) parseParameters (result  bool ) *ast .FieldList  {	if  p .trace  {		defer  un (trace (p , "Parameters" ))	}	if  !result  || p .tok  == token .LPAREN  {		lparen  := p .expect (token .LPAREN )		var  list  []*ast .Field 		if  p .tok  != token .RPAREN  {			list  = p .parseParameterList (nil , nil , token .RPAREN , !result )		}		rparen  := p .expect (token .RPAREN )		return  &ast .FieldList {Opening : lparen , List : list , Closing : rparen }	}	if  typ  := p .tryIdentOrType (); typ  != nil  {		list  := make ([]*ast .Field , 1 )		list [0 ] = &ast .Field {Type : typ }		return  &ast .FieldList {List : list }	}	return  nil }func  (p  *parser ) parseFuncType () *ast .FuncType  {	if  p .trace  {		defer  un (trace (p , "FuncType" ))	}	pos  := p .expect (token .FUNC )		if  p .tok  == token .LBRACK  {		tparams  := p .parseTypeParameters ()		if  tparams  != nil  {			p .error (tparams .Opening , "function type must have no type parameters" )		}	}	params  := p .parseParameters (false )	results  := p .parseParameters (true )	return  &ast .FuncType {Func : pos , Params : params , Results : results }}func  (p  *parser ) parseMethodSpec () *ast .Field  {	if  p .trace  {		defer  un (trace (p , "MethodSpec" ))	}	doc  := p .leadComment 	var  idents  []*ast .Ident 	var  typ  ast .Expr 	x  := p .parseTypeName (nil )	if  ident , _  := x .(*ast .Ident ); ident  != nil  {		switch  {		case  p .tok  == token .LBRACK :						lbrack  := p .pos 			p .next ()			p .exprLev ++			x  := p .parseExpr ()			p .exprLev --			if  name0 , _  := x .(*ast .Ident ); name0  != nil  && p .tok  != token .COMMA  && p .tok  != token .RBRACK  {								_ = p .parseParameterList (name0 , nil , token .RBRACK , false )				_ = p .expect (token .RBRACK )				p .error (lbrack , "interface method must have no type parameters" )								params  := p .parseParameters (false )				results  := p .parseParameters (true )				idents  = []*ast .Ident {ident }				typ  = &ast .FuncType {					Func :    token .NoPos ,					Params :  params ,					Results : results ,				}			} else  {								list  := []ast .Expr {x }				if  p .atComma ("type argument list" , token .RBRACK ) {					p .exprLev ++					p .next ()					for  p .tok  != token .RBRACK  && p .tok  != token .EOF  {						list  = append (list , p .parseType ())						if  !p .atComma ("type argument list" , token .RBRACK ) {							break 						}						p .next ()					}					p .exprLev --				}				rbrack  := p .expectClosing (token .RBRACK , "type argument list" )				typ  = packIndexExpr (ident , lbrack , list , rbrack )			}		case  p .tok  == token .LPAREN :						params  := p .parseParameters (false )			results  := p .parseParameters (true )			idents  = []*ast .Ident {ident }			typ  = &ast .FuncType {Func : token .NoPos , Params : params , Results : results }		default :						typ  = x 		}	} else  {				typ  = x 		if  p .tok  == token .LBRACK  {						typ  = p .parseTypeInstance (typ )		}	}		return  &ast .Field {Doc : doc , Names : idents , Type : typ }}func  (p  *parser ) embeddedElem (x  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "EmbeddedElem" ))	}	if  x  == nil  {		x  = p .embeddedTerm ()	}	for  p .tok  == token .OR  {		t  := new (ast .BinaryExpr )		t .OpPos  = p .pos 		t .Op  = token .OR 		p .next ()		t .X  = x 		t .Y  = p .embeddedTerm ()		x  = t 	}	return  x }func  (p  *parser ) embeddedTerm () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "EmbeddedTerm" ))	}	if  p .tok  == token .TILDE  {		t  := new (ast .UnaryExpr )		t .OpPos  = p .pos 		t .Op  = token .TILDE 		p .next ()		t .X  = p .parseType ()		return  t 	}	t  := p .tryIdentOrType ()	if  t  == nil  {		pos  := p .pos 		p .errorExpected (pos , "~ term or type" )		p .advance (exprEnd )		return  &ast .BadExpr {From : pos , To : p .pos }	}	return  t }func  (p  *parser ) parseInterfaceType () *ast .InterfaceType  {	if  p .trace  {		defer  un (trace (p , "InterfaceType" ))	}	pos  := p .expect (token .INTERFACE )	lbrace  := p .expect (token .LBRACE )	var  list  []*ast .Field parseElements :	for  {		switch  {		case  p .tok  == token .IDENT :			f  := p .parseMethodSpec ()			if  f .Names  == nil  {				f .Type  = p .embeddedElem (f .Type )			}			f .Comment  = p .expectSemi ()			list  = append (list , f )		case  p .tok  == token .TILDE :			typ  := p .embeddedElem (nil )			comment  := p .expectSemi ()			list  = append (list , &ast .Field {Type : typ , Comment : comment })		default :			if  t  := p .tryIdentOrType (); t  != nil  {				typ  := p .embeddedElem (t )				comment  := p .expectSemi ()				list  = append (list , &ast .Field {Type : typ , Comment : comment })			} else  {				break  parseElements 			}		}	}		rbrace  := p .expect (token .RBRACE )	return  &ast .InterfaceType {		Interface : pos ,		Methods : &ast .FieldList {			Opening : lbrace ,			List :    list ,			Closing : rbrace ,		},	}}func  (p  *parser ) parseMapType () *ast .MapType  {	if  p .trace  {		defer  un (trace (p , "MapType" ))	}	pos  := p .expect (token .MAP )	p .expect (token .LBRACK )	key  := p .parseType ()	p .expect (token .RBRACK )	value  := p .parseType ()	return  &ast .MapType {Map : pos , Key : key , Value : value }}func  (p  *parser ) parseChanType () *ast .ChanType  {	if  p .trace  {		defer  un (trace (p , "ChanType" ))	}	pos  := p .pos 	dir  := ast .SEND  | ast .RECV 	var  arrow  token .Pos 	if  p .tok  == token .CHAN  {		p .next ()		if  p .tok  == token .ARROW  {			arrow  = p .pos 			p .next ()			dir  = ast .SEND 		}	} else  {		arrow  = p .expect (token .ARROW )		p .expect (token .CHAN )		dir  = ast .RECV 	}	value  := p .parseType ()	return  &ast .ChanType {Begin : pos , Arrow : arrow , Dir : dir , Value : value }}func  (p  *parser ) parseTypeInstance (typ  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "TypeInstance" ))	}	opening  := p .expect (token .LBRACK )	p .exprLev ++	var  list  []ast .Expr 	for  p .tok  != token .RBRACK  && p .tok  != token .EOF  {		list  = append (list , p .parseType ())		if  !p .atComma ("type argument list" , token .RBRACK ) {			break 		}		p .next ()	}	p .exprLev --	closing  := p .expectClosing (token .RBRACK , "type argument list" )	if  len (list ) == 0  {		p .errorExpected (closing , "type argument list" )		return  &ast .IndexExpr {			X :      typ ,			Lbrack : opening ,			Index :  &ast .BadExpr {From : opening  + 1 , To : closing },			Rbrack : closing ,		}	}	return  packIndexExpr (typ , opening , list , closing )}func  (p  *parser ) tryIdentOrType () ast .Expr  {	defer  decNestLev (incNestLev (p ))	switch  p .tok  {	case  token .IDENT :		typ  := p .parseTypeName (nil )		if  p .tok  == token .LBRACK  {			typ  = p .parseTypeInstance (typ )		}		return  typ 	case  token .LBRACK :		lbrack  := p .expect (token .LBRACK )		return  p .parseArrayType (lbrack , nil )	case  token .STRUCT :		return  p .parseStructType ()	case  token .MUL :		return  p .parsePointerType ()	case  token .FUNC :		return  p .parseFuncType ()	case  token .INTERFACE :		return  p .parseInterfaceType ()	case  token .MAP :		return  p .parseMapType ()	case  token .CHAN , token .ARROW :		return  p .parseChanType ()	case  token .LPAREN :		lparen  := p .pos 		p .next ()		typ  := p .parseType ()		rparen  := p .expect (token .RPAREN )		return  &ast .ParenExpr {Lparen : lparen , X : typ , Rparen : rparen }	}		return  nil }func  (p  *parser ) parseStmtList () (list  []ast .Stmt ) {	if  p .trace  {		defer  un (trace (p , "StatementList" ))	}	for  p .tok  != token .CASE  && p .tok  != token .DEFAULT  && p .tok  != token .RBRACE  && p .tok  != token .EOF  {		list  = append (list , p .parseStmt ())	}	return }func  (p  *parser ) parseBody () *ast .BlockStmt  {	if  p .trace  {		defer  un (trace (p , "Body" ))	}	lbrace  := p .expect (token .LBRACE )	list  := p .parseStmtList ()	rbrace  := p .expect2 (token .RBRACE )	return  &ast .BlockStmt {Lbrace : lbrace , List : list , Rbrace : rbrace }}func  (p  *parser ) parseBlockStmt () *ast .BlockStmt  {	if  p .trace  {		defer  un (trace (p , "BlockStmt" ))	}	lbrace  := p .expect (token .LBRACE )	list  := p .parseStmtList ()	rbrace  := p .expect2 (token .RBRACE )	return  &ast .BlockStmt {Lbrace : lbrace , List : list , Rbrace : rbrace }}func  (p  *parser ) parseFuncTypeOrLit () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "FuncTypeOrLit" ))	}	typ  := p .parseFuncType ()	if  p .tok  != token .LBRACE  {				return  typ 	}	p .exprLev ++	body  := p .parseBody ()	p .exprLev --	return  &ast .FuncLit {Type : typ , Body : body }}func  (p  *parser ) parseOperand () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Operand" ))	}	switch  p .tok  {	case  token .IDENT :		x  := p .parseIdent ()		return  x 	case  token .INT , token .FLOAT , token .IMAG , token .CHAR , token .STRING :		x  := &ast .BasicLit {ValuePos : p .pos , Kind : p .tok , Value : p .lit }		p .next ()		return  x 	case  token .LPAREN :		lparen  := p .pos 		p .next ()		p .exprLev ++		x  := p .parseRhs () 		p .exprLev --		rparen  := p .expect (token .RPAREN )		return  &ast .ParenExpr {Lparen : lparen , X : x , Rparen : rparen }	case  token .FUNC :		return  p .parseFuncTypeOrLit ()	}	if  typ  := p .tryIdentOrType (); typ  != nil  { 				_ , isIdent  := typ .(*ast .Ident )		assert (!isIdent , "type cannot be identifier" )		return  typ 	}		pos  := p .pos 	p .errorExpected (pos , "operand" )	p .advance (stmtStart )	return  &ast .BadExpr {From : pos , To : p .pos }}func  (p  *parser ) parseSelector (x  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Selector" ))	}	sel  := p .parseIdent ()	return  &ast .SelectorExpr {X : x , Sel : sel }}func  (p  *parser ) parseTypeAssertion (x  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "TypeAssertion" ))	}	lparen  := p .expect (token .LPAREN )	var  typ  ast .Expr 	if  p .tok  == token .TYPE  {				p .next ()	} else  {		typ  = p .parseType ()	}	rparen  := p .expect (token .RPAREN )	return  &ast .TypeAssertExpr {X : x , Type : typ , Lparen : lparen , Rparen : rparen }}func  (p  *parser ) parseIndexOrSliceOrInstance (x  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "parseIndexOrSliceOrInstance" ))	}	lbrack  := p .expect (token .LBRACK )	if  p .tok  == token .RBRACK  {				p .errorExpected (p .pos , "operand" )		rbrack  := p .pos 		p .next ()		return  &ast .IndexExpr {			X :      x ,			Lbrack : lbrack ,			Index :  &ast .BadExpr {From : rbrack , To : rbrack },			Rbrack : rbrack ,		}	}	p .exprLev ++	const  N  = 3  	var  args  []ast .Expr 	var  index  [N ]ast .Expr 	var  colons  [N  - 1 ]token .Pos 	if  p .tok  != token .COLON  {				index [0 ] = p .parseRhs ()	}	ncolons  := 0 	switch  p .tok  {	case  token .COLON :				for  p .tok  == token .COLON  && ncolons  < len (colons ) {			colons [ncolons ] = p .pos 			ncolons ++			p .next ()			if  p .tok  != token .COLON  && p .tok  != token .RBRACK  && p .tok  != token .EOF  {				index [ncolons ] = p .parseRhs ()			}		}	case  token .COMMA :				args  = append (args , index [0 ])		for  p .tok  == token .COMMA  {			p .next ()			if  p .tok  != token .RBRACK  && p .tok  != token .EOF  {				args  = append (args , p .parseType ())			}		}	}	p .exprLev --	rbrack  := p .expect (token .RBRACK )	if  ncolons  > 0  {				slice3  := false 		if  ncolons  == 2  {			slice3  = true 						if  index [1 ] == nil  {				p .error (colons [0 ], "middle index required in 3-index slice" )				index [1 ] = &ast .BadExpr {From : colons [0 ] + 1 , To : colons [1 ]}			}			if  index [2 ] == nil  {				p .error (colons [1 ], "final index required in 3-index slice" )				index [2 ] = &ast .BadExpr {From : colons [1 ] + 1 , To : rbrack }			}		}		return  &ast .SliceExpr {X : x , Lbrack : lbrack , Low : index [0 ], High : index [1 ], Max : index [2 ], Slice3 : slice3 , Rbrack : rbrack }	}	if  len (args ) == 0  {				return  &ast .IndexExpr {X : x , Lbrack : lbrack , Index : index [0 ], Rbrack : rbrack }	}		return  packIndexExpr (x , lbrack , args , rbrack )}func  (p  *parser ) parseCallOrConversion (fun  ast .Expr ) *ast .CallExpr  {	if  p .trace  {		defer  un (trace (p , "CallOrConversion" ))	}	lparen  := p .expect (token .LPAREN )	p .exprLev ++	var  list  []ast .Expr 	var  ellipsis  token .Pos 	for  p .tok  != token .RPAREN  && p .tok  != token .EOF  && !ellipsis .IsValid () {		list  = append (list , p .parseRhs ()) 		if  p .tok  == token .ELLIPSIS  {			ellipsis  = p .pos 			p .next ()		}		if  !p .atComma ("argument list" , token .RPAREN ) {			break 		}		p .next ()	}	p .exprLev --	rparen  := p .expectClosing (token .RPAREN , "argument list" )	return  &ast .CallExpr {Fun : fun , Lparen : lparen , Args : list , Ellipsis : ellipsis , Rparen : rparen }}func  (p  *parser ) parseValue () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Element" ))	}	if  p .tok  == token .LBRACE  {		return  p .parseLiteralValue (nil )	}	x  := p .parseExpr ()	return  x }func  (p  *parser ) parseElement () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Element" ))	}	x  := p .parseValue ()	if  p .tok  == token .COLON  {		colon  := p .pos 		p .next ()		x  = &ast .KeyValueExpr {Key : x , Colon : colon , Value : p .parseValue ()}	}	return  x }func  (p  *parser ) parseElementList () (list  []ast .Expr ) {	if  p .trace  {		defer  un (trace (p , "ElementList" ))	}	for  p .tok  != token .RBRACE  && p .tok  != token .EOF  {		list  = append (list , p .parseElement ())		if  !p .atComma ("composite literal" , token .RBRACE ) {			break 		}		p .next ()	}	return }func  (p  *parser ) parseLiteralValue (typ  ast .Expr ) ast .Expr  {	defer  decNestLev (incNestLev (p ))	if  p .trace  {		defer  un (trace (p , "LiteralValue" ))	}	lbrace  := p .expect (token .LBRACE )	var  elts  []ast .Expr 	p .exprLev ++	if  p .tok  != token .RBRACE  {		elts  = p .parseElementList ()	}	p .exprLev --	rbrace  := p .expectClosing (token .RBRACE , "composite literal" )	return  &ast .CompositeLit {Type : typ , Lbrace : lbrace , Elts : elts , Rbrace : rbrace }}func  (p  *parser ) parsePrimaryExpr (x  ast .Expr ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "PrimaryExpr" ))	}	if  x  == nil  {		x  = p .parseOperand ()	}		var  n  int 	defer  func () { p .nestLev  -= n  }()	for  n  = 1 ; ; n ++ {		incNestLev (p )		switch  p .tok  {		case  token .PERIOD :			p .next ()			switch  p .tok  {			case  token .IDENT :				x  = p .parseSelector (x )			case  token .LPAREN :				x  = p .parseTypeAssertion (x )			default :				pos  := p .pos 				p .errorExpected (pos , "selector or type assertion" )								if  p .tok  != token .RBRACE  {					p .next () 				}				sel  := &ast .Ident {NamePos : pos , Name : "_" }				x  = &ast .SelectorExpr {X : x , Sel : sel }			}		case  token .LBRACK :			x  = p .parseIndexOrSliceOrInstance (x )		case  token .LPAREN :			x  = p .parseCallOrConversion (x )		case  token .LBRACE :						t  := ast .Unparen (x )						switch  t .(type ) {			case  *ast .BadExpr , *ast .Ident , *ast .SelectorExpr :				if  p .exprLev  < 0  {					return  x 				}							case  *ast .IndexExpr , *ast .IndexListExpr :				if  p .exprLev  < 0  {					return  x 				}							case  *ast .ArrayType , *ast .StructType , *ast .MapType :							default :				return  x 			}			if  t  != x  {				p .error (t .Pos (), "cannot parenthesize type in composite literal" )							}			x  = p .parseLiteralValue (x )		default :			return  x 		}	}}func  (p  *parser ) parseUnaryExpr () ast .Expr  {	defer  decNestLev (incNestLev (p ))	if  p .trace  {		defer  un (trace (p , "UnaryExpr" ))	}	switch  p .tok  {	case  token .ADD , token .SUB , token .NOT , token .XOR , token .AND , token .TILDE :		pos , op  := p .pos , p .tok 		p .next ()		x  := p .parseUnaryExpr ()		return  &ast .UnaryExpr {OpPos : pos , Op : op , X : x }	case  token .ARROW :				arrow  := p .pos 		p .next ()				x  := p .parseUnaryExpr ()				if  typ , ok  := x .(*ast .ChanType ); ok  {									dir  := ast .SEND 			for  ok  && dir  == ast .SEND  {				if  typ .Dir  == ast .RECV  {										p .errorExpected (typ .Arrow , "'chan'" )				}				arrow , typ .Begin , typ .Arrow  = typ .Arrow , arrow , arrow 				dir , typ .Dir  = typ .Dir , ast .RECV 				typ , ok  = typ .Value .(*ast .ChanType )			}			if  dir  == ast .SEND  {				p .errorExpected (arrow , "channel type" )			}			return  x 		}				return  &ast .UnaryExpr {OpPos : arrow , Op : token .ARROW , X : x }	case  token .MUL :				pos  := p .pos 		p .next ()		x  := p .parseUnaryExpr ()		return  &ast .StarExpr {Star : pos , X : x }	}	return  p .parsePrimaryExpr (nil )}func  (p  *parser ) tokPrec () (token .Token , int ) {	tok  := p .tok 	if  p .inRhs  && tok  == token .ASSIGN  {		tok  = token .EQL 	}	return  tok , tok .Precedence ()}func  (p  *parser ) parseBinaryExpr (x  ast .Expr , prec1  int ) ast .Expr  {	if  p .trace  {		defer  un (trace (p , "BinaryExpr" ))	}	if  x  == nil  {		x  = p .parseUnaryExpr ()	}		var  n  int 	defer  func () { p .nestLev  -= n  }()	for  n  = 1 ; ; n ++ {		incNestLev (p )		op , oprec  := p .tokPrec ()		if  oprec  < prec1  {			return  x 		}		pos  := p .expect (op )		y  := p .parseBinaryExpr (nil , oprec +1 )		x  = &ast .BinaryExpr {X : x , OpPos : pos , Op : op , Y : y }	}}func  (p  *parser ) parseExpr () ast .Expr  {	if  p .trace  {		defer  un (trace (p , "Expression" ))	}	return  p .parseBinaryExpr (nil , token .LowestPrec +1 )}func  (p  *parser ) parseRhs () ast .Expr  {	old  := p .inRhs 	p .inRhs  = true 	x  := p .parseExpr ()	p .inRhs  = old 	return  x }const  (	basic = iota 	labelOk	rangeOk)func  (p  *parser ) parseSimpleStmt (mode  int ) (ast .Stmt , bool ) {	if  p .trace  {		defer  un (trace (p , "SimpleStmt" ))	}	x  := p .parseList (false )	switch  p .tok  {	case 		token .DEFINE , token .ASSIGN , token .ADD_ASSIGN ,		token .SUB_ASSIGN , token .MUL_ASSIGN , token .QUO_ASSIGN ,		token .REM_ASSIGN , token .AND_ASSIGN , token .OR_ASSIGN ,		token .XOR_ASSIGN , token .SHL_ASSIGN , token .SHR_ASSIGN , token .AND_NOT_ASSIGN :				pos , tok  := p .pos , p .tok 		p .next ()		var  y  []ast .Expr 		isRange  := false 		if  mode  == rangeOk  && p .tok  == token .RANGE  && (tok  == token .DEFINE  || tok  == token .ASSIGN ) {			pos  := p .pos 			p .next ()			y  = []ast .Expr {&ast .UnaryExpr {OpPos : pos , Op : token .RANGE , X : p .parseRhs ()}}			isRange  = true 		} else  {			y  = p .parseList (true )		}		return  &ast .AssignStmt {Lhs : x , TokPos : pos , Tok : tok , Rhs : y }, isRange 	}	if  len (x ) > 1  {		p .errorExpected (x [0 ].Pos (), "1 expression" )			}	switch  p .tok  {	case  token .COLON :				colon  := p .pos 		p .next ()		if  label , isIdent  := x [0 ].(*ast .Ident ); mode  == labelOk  && isIdent  {						stmt  := &ast .LabeledStmt {Label : label , Colon : colon , Stmt : p .parseStmt ()}			return  stmt , false 		}				p .error (colon , "illegal label declaration" )		return  &ast .BadStmt {From : x [0 ].Pos (), To : colon  + 1 }, false 	case  token .ARROW :				arrow  := p .pos 		p .next ()		y  := p .parseRhs ()		return  &ast .SendStmt {Chan : x [0 ], Arrow : arrow , Value : y }, false 	case  token .INC , token .DEC :				s  := &ast .IncDecStmt {X : x [0 ], TokPos : p .pos , Tok : p .tok }		p .next ()		return  s , false 	}		return  &ast .ExprStmt {X : x [0 ]}, false }func  (p  *parser ) parseCallExpr (callType  string ) *ast .CallExpr  {	x  := p .parseRhs () 	if  t  := ast .Unparen (x ); t  != x  {		p .error (x .Pos (), fmt .Sprintf ("expression in %s must not be parenthesized" , callType ))		x  = t 	}	if  call , isCall  := x .(*ast .CallExpr ); isCall  {		return  call 	}	if  _ , isBad  := x .(*ast .BadExpr ); !isBad  {				p .error (p .safePos (x .End ()), fmt .Sprintf ("expression in %s must be function call" , callType ))	}	return  nil }func  (p  *parser ) parseGoStmt () ast .Stmt  {	if  p .trace  {		defer  un (trace (p , "GoStmt" ))	}	pos  := p .expect (token .GO )	call  := p .parseCallExpr ("go" )	p .expectSemi ()	if  call  == nil  {		return  &ast .BadStmt {From : pos , To : pos  + 2 } 	}	return  &ast .GoStmt {Go : pos , Call : call }}func  (p  *parser ) parseDeferStmt () ast .Stmt  {	if  p .trace  {		defer  un (trace (p , "DeferStmt" ))	}	pos  := p .expect (token .DEFER )	call  := p .parseCallExpr ("defer" )	p .expectSemi ()	if  call  == nil  {		return  &ast .BadStmt {From : pos , To : pos  + 5 } 	}	return  &ast .DeferStmt {Defer : pos , Call : call }}func  (p  *parser ) parseReturnStmt () *ast .ReturnStmt  {	if  p .trace  {		defer  un (trace (p , "ReturnStmt" ))	}	pos  := p .pos 	p .expect (token .RETURN )	var  x  []ast .Expr 	if  p .tok  != token .SEMICOLON  && p .tok  != token .RBRACE  {		x  = p .parseList (true )	}	p .expectSemi ()	return  &ast .ReturnStmt {Return : pos , Results : x }}func  (p  *parser ) parseBranchStmt (tok  token .Token ) *ast .BranchStmt  {	if  p .trace  {		defer  un (trace (p , "BranchStmt" ))	}	pos  := p .expect (tok )	var  label  *ast .Ident 	if  tok  == token .GOTO  || ((tok  == token .CONTINUE  || tok  == token .BREAK ) && p .tok  == token .IDENT ) {		label  = p .parseIdent ()	}	p .expectSemi ()	return  &ast .BranchStmt {TokPos : pos , Tok : tok , Label : label }}func  (p  *parser ) makeExpr (s  ast .Stmt , want  string ) ast .Expr  {	if  s  == nil  {		return  nil 	}	if  es , isExpr  := s .(*ast .ExprStmt ); isExpr  {		return  es .X 	}	found  := "simple statement" 	if  _ , isAss  := s .(*ast .AssignStmt ); isAss  {		found  = "assignment" 	}	p .error (s .Pos (), fmt .Sprintf ("expected %s, found %s (missing parentheses around composite literal?)" , want , found ))	return  &ast .BadExpr {From : s .Pos (), To : p .safePos (s .End ())}}func  (p  *parser ) parseIfHeader () (init  ast .Stmt , cond  ast .Expr ) {	if  p .tok  == token .LBRACE  {		p .error (p .pos , "missing condition in if statement" )		cond  = &ast .BadExpr {From : p .pos , To : p .pos }		return 	}		prevLev  := p .exprLev 	p .exprLev  = -1 	if  p .tok  != token .SEMICOLON  {				if  p .tok  == token .VAR  {			p .next ()			p .error (p .pos , "var declaration not allowed in if initializer" )		}		init , _ = p .parseSimpleStmt (basic )	}	var  condStmt  ast .Stmt 	var  semi  struct  {		pos  token .Pos 		lit  string  	}	if  p .tok  != token .LBRACE  {		if  p .tok  == token .SEMICOLON  {			semi .pos  = p .pos 			semi .lit  = p .lit 			p .next ()		} else  {			p .expect (token .SEMICOLON )		}		if  p .tok  != token .LBRACE  {			condStmt , _ = p .parseSimpleStmt (basic )		}	} else  {		condStmt  = init 		init  = nil 	}	if  condStmt  != nil  {		cond  = p .makeExpr (condStmt , "boolean expression" )	} else  if  semi .pos .IsValid () {		if  semi .lit  == "\n"  {			p .error (semi .pos , "unexpected newline, expecting { after if clause" )		} else  {			p .error (semi .pos , "missing condition in if statement" )		}	}		if  cond  == nil  {		cond  = &ast .BadExpr {From : p .pos , To : p .pos }	}	p .exprLev  = prevLev 	return }func  (p  *parser ) parseIfStmt () *ast .IfStmt  {	defer  decNestLev (incNestLev (p ))	if  p .trace  {		defer  un (trace (p , "IfStmt" ))	}	pos  := p .expect (token .IF )	init , cond  := p .parseIfHeader ()	body  := p .parseBlockStmt ()	var  else_  ast .Stmt 	if  p .tok  == token .ELSE  {		p .next ()		switch  p .tok  {		case  token .IF :			else_  = p .parseIfStmt ()		case  token .LBRACE :			else_  = p .parseBlockStmt ()			p .expectSemi ()		default :			p .errorExpected (p .pos , "if statement or block" )			else_  = &ast .BadStmt {From : p .pos , To : p .pos }		}	} else  {		p .expectSemi ()	}	return  &ast .IfStmt {If : pos , Init : init , Cond : cond , Body : body , Else : else_ }}func  (p  *parser ) parseCaseClause () *ast .CaseClause  {	if  p .trace  {		defer  un (trace (p , "CaseClause" ))	}	pos  := p .pos 	var  list  []ast .Expr 	if  p .tok  == token .CASE  {		p .next ()		list  = p .parseList (true )	} else  {		p .expect (token .DEFAULT )	}	colon  := p .expect (token .COLON )	body  := p .parseStmtList ()	return  &ast .CaseClause {Case : pos , List : list , Colon : colon , Body : body }}func  isTypeSwitchAssert(x  ast .Expr ) bool  {	a , ok  := x .(*ast .TypeAssertExpr )	return  ok  && a .Type  == nil }func  (p  *parser ) isTypeSwitchGuard (s  ast .Stmt ) bool  {	switch  t := s .(type ) {	case  *ast .ExprStmt :				return  isTypeSwitchAssert (t .X )	case  *ast .AssignStmt :				if  len (t .Lhs ) == 1  && len (t .Rhs ) == 1  && isTypeSwitchAssert (t .Rhs [0 ]) {			switch  t .Tok  {			case  token .ASSIGN :								p .error (t .TokPos , "expected ':=', found '='" )				fallthrough 			case  token .DEFINE :				return  true 			}		}	}	return  false }func  (p  *parser ) parseSwitchStmt () ast .Stmt  {	if  p .trace  {		defer  un (trace (p , "SwitchStmt" ))	}	pos  := p .expect (token .SWITCH )	var  s1 , s2  ast .Stmt 	if  p .tok  != token .LBRACE  {		prevLev  := p .exprLev 		p .exprLev  = -1 		if  p .tok  != token .SEMICOLON  {			s2 , _ = p .parseSimpleStmt (basic )		}		if  p .tok  == token .SEMICOLON  {			p .next ()			s1  = s2 			s2  = nil 			if  p .tok  != token .LBRACE  {								s2 , _ = p .parseSimpleStmt (basic )			}		}		p .exprLev  = prevLev 	}	typeSwitch  := p .isTypeSwitchGuard (s2 )	lbrace  := p .expect (token .LBRACE )	var  list  []ast .Stmt 	for  p .tok  == token .CASE  || p .tok  == token .DEFAULT  {		list  = append (list , p .parseCaseClause ())	}	rbrace  := p .expect (token .RBRACE )	p .expectSemi ()	body  := &ast .BlockStmt {Lbrace : lbrace , List : list , Rbrace : rbrace }	if  typeSwitch  {		return  &ast .TypeSwitchStmt {Switch : pos , Init : s1 , Assign : s2 , Body : body }	}	return  &ast .SwitchStmt {Switch : pos , Init : s1 , Tag : p .makeExpr (s2 , "switch expression" ), Body : body }}func  (p  *parser ) parseCommClause () *ast .CommClause  {	if  p .trace  {		defer  un (trace (p , "CommClause" ))	}	pos  := p .pos 	var  comm  ast .Stmt 	if  p .tok  == token .CASE  {		p .next ()		lhs  := p .parseList (false )		if  p .tok  == token .ARROW  {						if  len (lhs ) > 1  {				p .errorExpected (lhs [0 ].Pos (), "1 expression" )							}			arrow  := p .pos 			p .next ()			rhs  := p .parseRhs ()			comm  = &ast .SendStmt {Chan : lhs [0 ], Arrow : arrow , Value : rhs }		} else  {						if  tok  := p .tok ; tok  == token .ASSIGN  || tok  == token .DEFINE  {								if  len (lhs ) > 2  {					p .errorExpected (lhs [0 ].Pos (), "1 or 2 expressions" )										lhs  = lhs [0 :2 ]				}				pos  := p .pos 				p .next ()				rhs  := p .parseRhs ()				comm  = &ast .AssignStmt {Lhs : lhs , TokPos : pos , Tok : tok , Rhs : []ast .Expr {rhs }}			} else  {								if  len (lhs ) > 1  {					p .errorExpected (lhs [0 ].Pos (), "1 expression" )									}				comm  = &ast .ExprStmt {X : lhs [0 ]}			}		}	} else  {		p .expect (token .DEFAULT )	}	colon  := p .expect (token .COLON )	body  := p .parseStmtList ()	return  &ast .CommClause {Case : pos , Comm : comm , Colon : colon , Body : body }}func  (p  *parser ) parseSelectStmt () *ast .SelectStmt  {	if  p .trace  {		defer  un (trace (p , "SelectStmt" ))	}	pos  := p .expect (token .SELECT )	lbrace  := p .expect (token .LBRACE )	var  list  []ast .Stmt 	for  p .tok  == token .CASE  || p .tok  == token .DEFAULT  {		list  = append (list , p .parseCommClause ())	}	rbrace  := p .expect (token .RBRACE )	p .expectSemi ()	body  := &ast .BlockStmt {Lbrace : lbrace , List : list , Rbrace : rbrace }	return  &ast .SelectStmt {Select : pos , Body : body }}func  (p  *parser ) parseForStmt () ast .Stmt  {	if  p .trace  {		defer  un (trace (p , "ForStmt" ))	}	pos  := p .expect (token .FOR )	var  s1 , s2 , s3  ast .Stmt 	var  isRange  bool 	if  p .tok  != token .LBRACE  {		prevLev  := p .exprLev 		p .exprLev  = -1 		if  p .tok  != token .SEMICOLON  {			if  p .tok  == token .RANGE  {								pos  := p .pos 				p .next ()				y  := []ast .Expr {&ast .UnaryExpr {OpPos : pos , Op : token .RANGE , X : p .parseRhs ()}}				s2  = &ast .AssignStmt {Rhs : y }				isRange  = true 			} else  {				s2 , isRange  = p .parseSimpleStmt (rangeOk )			}		}		if  !isRange  && p .tok  == token .SEMICOLON  {			p .next ()			s1  = s2 			s2  = nil 			if  p .tok  != token .SEMICOLON  {				s2 , _ = p .parseSimpleStmt (basic )			}			p .expectSemi ()			if  p .tok  != token .LBRACE  {				s3 , _ = p .parseSimpleStmt (basic )			}		}		p .exprLev  = prevLev 	}	body  := p .parseBlockStmt ()	p .expectSemi ()	if  isRange  {		as  := s2 .(*ast .AssignStmt )				var  key , value  ast .Expr 		switch  len (as .Lhs ) {		case  0 :					case  1 :			key  = as .Lhs [0 ]		case  2 :			key , value  = as .Lhs [0 ], as .Lhs [1 ]		default :			p .errorExpected (as .Lhs [len (as .Lhs )-1 ].Pos (), "at most 2 expressions" )			return  &ast .BadStmt {From : pos , To : p .safePos (body .End ())}		}				x  := as .Rhs [0 ].(*ast .UnaryExpr ).X 		return  &ast .RangeStmt {			For :    pos ,			Key :    key ,			Value :  value ,			TokPos : as .TokPos ,			Tok :    as .Tok ,			Range :  as .Rhs [0 ].Pos (),			X :      x ,			Body :   body ,		}	}		return  &ast .ForStmt {		For :  pos ,		Init : s1 ,		Cond : p .makeExpr (s2 , "boolean or range expression" ),		Post : s3 ,		Body : body ,	}}func  (p  *parser ) parseStmt () (s  ast .Stmt ) {	defer  decNestLev (incNestLev (p ))	if  p .trace  {		defer  un (trace (p , "Statement" ))	}	switch  p .tok  {	case  token .CONST , token .TYPE , token .VAR :		s  = &ast .DeclStmt {Decl : p .parseDecl (stmtStart )}	case 				token .IDENT , token .INT , token .FLOAT , token .IMAG , token .CHAR , token .STRING , token .FUNC , token .LPAREN , 		token .LBRACK , token .STRUCT , token .MAP , token .CHAN , token .INTERFACE , 		token .ADD , token .SUB , token .MUL , token .AND , token .XOR , token .ARROW , token .NOT : 		s , _ = p .parseSimpleStmt (labelOk )				if  _ , isLabeledStmt  := s .(*ast .LabeledStmt ); !isLabeledStmt  {			p .expectSemi ()		}	case  token .GO :		s  = p .parseGoStmt ()	case  token .DEFER :		s  = p .parseDeferStmt ()	case  token .RETURN :		s  = p .parseReturnStmt ()	case  token .BREAK , token .CONTINUE , token .GOTO , token .FALLTHROUGH :		s  = p .parseBranchStmt (p .tok )	case  token .LBRACE :		s  = p .parseBlockStmt ()		p .expectSemi ()	case  token .IF :		s  = p .parseIfStmt ()	case  token .SWITCH :		s  = p .parseSwitchStmt ()	case  token .SELECT :		s  = p .parseSelectStmt ()	case  token .FOR :		s  = p .parseForStmt ()	case  token .SEMICOLON :				s  = &ast .EmptyStmt {Semicolon : p .pos , Implicit : p .lit  == "\n" }		p .next ()	case  token .RBRACE :				s  = &ast .EmptyStmt {Semicolon : p .pos , Implicit : true }	default :				pos  := p .pos 		p .errorExpected (pos , "statement" )		p .advance (stmtStart )		s  = &ast .BadStmt {From : pos , To : p .pos }	}	return }type  parseSpecFunction func (doc *ast .CommentGroup , keyword token .Token , iota int ) ast .Spec func  (p  *parser ) parseImportSpec (doc  *ast .CommentGroup , _  token .Token , _  int ) ast .Spec  {	if  p .trace  {		defer  un (trace (p , "ImportSpec" ))	}	var  ident  *ast .Ident 	switch  p .tok  {	case  token .IDENT :		ident  = p .parseIdent ()	case  token .PERIOD :		ident  = &ast .Ident {NamePos : p .pos , Name : "." }		p .next ()	}	pos  := p .pos 	var  path  string 	if  p .tok  == token .STRING  {		path  = p .lit 		p .next ()	} else  if  p .tok .IsLiteral () {		p .error (pos , "import path must be a string" )		p .next ()	} else  {		p .error (pos , "missing import path" )		p .advance (exprEnd )	}	comment  := p .expectSemi ()		spec  := &ast .ImportSpec {		Doc :     doc ,		Name :    ident ,		Path :    &ast .BasicLit {ValuePos : pos , Kind : token .STRING , Value : path },		Comment : comment ,	}	p .imports  = append (p .imports , spec )	return  spec }func  (p  *parser ) parseValueSpec (doc  *ast .CommentGroup , keyword  token .Token , iota  int ) ast .Spec  {	if  p .trace  {		defer  un (trace (p , keyword .String ()+"Spec" ))	}	idents  := p .parseIdentList ()	var  typ  ast .Expr 	var  values  []ast .Expr 	switch  keyword  {	case  token .CONST :				if  p .tok  != token .EOF  && p .tok  != token .SEMICOLON  && p .tok  != token .RPAREN  {			typ  = p .tryIdentOrType ()			if  p .tok  == token .ASSIGN  {				p .next ()				values  = p .parseList (true )			}		}	case  token .VAR :		if  p .tok  != token .ASSIGN  {			typ  = p .parseType ()		}		if  p .tok  == token .ASSIGN  {			p .next ()			values  = p .parseList (true )		}	default :		panic ("unreachable" )	}	comment  := p .expectSemi ()	spec  := &ast .ValueSpec {		Doc :     doc ,		Names :   idents ,		Type :    typ ,		Values :  values ,		Comment : comment ,	}	return  spec }func  (p  *parser ) parseGenericType (spec  *ast .TypeSpec , openPos  token .Pos , name0  *ast .Ident , typ0  ast .Expr ) {	if  p .trace  {		defer  un (trace (p , "parseGenericType" ))	}	list  := p .parseParameterList (name0 , typ0 , token .RBRACK , false )	closePos  := p .expect (token .RBRACK )	spec .TypeParams  = &ast .FieldList {Opening : openPos , List : list , Closing : closePos }	if  p .tok  == token .ASSIGN  {				spec .Assign  = p .pos 		p .next ()	}	spec .Type  = p .parseType ()}func  (p  *parser ) parseTypeSpec (doc  *ast .CommentGroup , _  token .Token , _  int ) ast .Spec  {	if  p .trace  {		defer  un (trace (p , "TypeSpec" ))	}	name  := p .parseIdent ()	spec  := &ast .TypeSpec {Doc : doc , Name : name }	if  p .tok  == token .LBRACK  {				lbrack  := p .pos 		p .next ()		if  p .tok  == token .IDENT  {						var  x  ast .Expr  = p .parseIdent ()			if  p .tok  != token .LBRACK  {								p .exprLev ++				lhs  := p .parsePrimaryExpr (x )				x  = p .parseBinaryExpr (lhs , token .LowestPrec +1 )				p .exprLev --			}						if  pname , ptype  := extractName (x , p .tok  == token .COMMA ); pname  != nil  && (ptype  != nil  || p .tok  != token .RBRACK ) {								p .parseGenericType (spec , lbrack , pname , ptype ) 			} else  {								spec .Type  = p .parseArrayType (lbrack , x )			}		} else  {						spec .Type  = p .parseArrayType (lbrack , nil )		}	} else  {				if  p .tok  == token .ASSIGN  {						spec .Assign  = p .pos 			p .next ()		}		spec .Type  = p .parseType ()	}	spec .Comment  = p .expectSemi ()	return  spec }func  extractName(x  ast .Expr , force  bool ) (*ast .Ident , ast .Expr ) {	switch  x := x .(type ) {	case  *ast .Ident :		return  x , nil 	case  *ast .BinaryExpr :		switch  x .Op  {		case  token .MUL :			if  name , _  := x .X .(*ast .Ident ); name  != nil  && (force  || isTypeElem (x .Y )) {								return  name , &ast .StarExpr {Star : x .OpPos , X : x .Y }			}		case  token .OR :			if  name , lhs  := extractName (x .X , force  || isTypeElem (x .Y )); name  != nil  && lhs  != nil  {								op  := *x 				op .X  = lhs 				return  name , &op 			}		}	case  *ast .CallExpr :		if  name , _  := x .Fun .(*ast .Ident ); name  != nil  {			if  len (x .Args ) == 1  && x .Ellipsis  == token .NoPos  && (force  || isTypeElem (x .Args [0 ])) {								return  name , &ast .ParenExpr {					Lparen : x .Lparen ,					X :      x .Args [0 ],					Rparen : x .Rparen ,				}			}		}	}	return  nil , x }func  isTypeElem(x  ast .Expr ) bool  {	switch  x := x .(type ) {	case  *ast .ArrayType , *ast .StructType , *ast .FuncType , *ast .InterfaceType , *ast .MapType , *ast .ChanType :		return  true 	case  *ast .BinaryExpr :		return  isTypeElem (x .X ) || isTypeElem (x .Y )	case  *ast .UnaryExpr :		return  x .Op  == token .TILDE 	case  *ast .ParenExpr :		return  isTypeElem (x .X )	}	return  false }func  (p  *parser ) parseGenDecl (keyword  token .Token , f  parseSpecFunction ) *ast .GenDecl  {	if  p .trace  {		defer  un (trace (p , "GenDecl(" +keyword .String ()+")" ))	}	doc  := p .leadComment 	pos  := p .expect (keyword )	var  lparen , rparen  token .Pos 	var  list  []ast .Spec 	if  p .tok  == token .LPAREN  {		lparen  = p .pos 		p .next ()		for  iota  := 0 ; p .tok  != token .RPAREN  && p .tok  != token .EOF ; iota ++ {			list  = append (list , f (p .leadComment , keyword , iota ))		}		rparen  = p .expect (token .RPAREN )		p .expectSemi ()	} else  {		list  = append (list , f (nil , keyword , 0 ))	}	return  &ast .GenDecl {		Doc :    doc ,		TokPos : pos ,		Tok :    keyword ,		Lparen : lparen ,		Specs :  list ,		Rparen : rparen ,	}}func  (p  *parser ) parseFuncDecl () *ast .FuncDecl  {	if  p .trace  {		defer  un (trace (p , "FunctionDecl" ))	}	doc  := p .leadComment 	pos  := p .expect (token .FUNC )	var  recv  *ast .FieldList 	if  p .tok  == token .LPAREN  {		recv  = p .parseParameters (false )	}	ident  := p .parseIdent ()	var  tparams  *ast .FieldList 	if  p .tok  == token .LBRACK  {		tparams  = p .parseTypeParameters ()		if  recv  != nil  && tparams  != nil  {						p .error (tparams .Opening , "method must have no type parameters" )			tparams  = nil 		}	}	params  := p .parseParameters (false )	results  := p .parseParameters (true )	var  body  *ast .BlockStmt 	switch  p .tok  {	case  token .LBRACE :		body  = p .parseBody ()		p .expectSemi ()	case  token .SEMICOLON :		p .next ()		if  p .tok  == token .LBRACE  {						p .error (p .pos , "unexpected semicolon or newline before {" )			body  = p .parseBody ()			p .expectSemi ()		}	default :		p .expectSemi ()	}	decl  := &ast .FuncDecl {		Doc :  doc ,		Recv : recv ,		Name : ident ,		Type : &ast .FuncType {			Func :       pos ,			TypeParams : tparams ,			Params :     params ,			Results :    results ,		},		Body : body ,	}	return  decl }func  (p  *parser ) parseDecl (sync  map [token .Token ]bool ) ast .Decl  {	if  p .trace  {		defer  un (trace (p , "Declaration" ))	}	var  f  parseSpecFunction 	switch  p .tok  {	case  token .IMPORT :		f  = p .parseImportSpec 	case  token .CONST , token .VAR :		f  = p .parseValueSpec 	case  token .TYPE :		f  = p .parseTypeSpec 	case  token .FUNC :		return  p .parseFuncDecl ()	default :		pos  := p .pos 		p .errorExpected (pos , "declaration" )		p .advance (sync )		return  &ast .BadDecl {From : pos , To : p .pos }	}	return  p .parseGenDecl (p .tok , f )}func  (p  *parser ) parseFile () *ast .File  {	if  p .trace  {		defer  un (trace (p , "File" ))	}		if  p .errors .Len () != 0  {		return  nil 	}		doc  := p .leadComment 	pos  := p .expect (token .PACKAGE )		ident  := p .parseIdent ()	if  ident .Name  == "_"  && p .mode &DeclarationErrors  != 0  {		p .error (p .pos , "invalid package name _" )	}	p .expectSemi ()		if  p .errors .Len () != 0  {		return  nil 	}	var  decls  []ast .Decl 	if  p .mode &PackageClauseOnly  == 0  {				for  p .tok  == token .IMPORT  {			decls  = append (decls , p .parseGenDecl (token .IMPORT , p .parseImportSpec ))		}		if  p .mode &ImportsOnly  == 0  {						prev  := token .IMPORT 			for  p .tok  != token .EOF  {								if  p .tok  == token .IMPORT  && prev  != token .IMPORT  {					p .error (p .pos , "imports must appear before other declarations" )				}				prev  = p .tok 				decls  = append (decls , p .parseDecl (declStart ))			}		}	}	f  := &ast .File {		Doc :     doc ,		Package : pos ,		Name :    ident ,		Decls :   decls ,				Imports :   p .imports ,		Comments :  p .comments ,		GoVersion : p .goVersion ,	}	var  declErr  func (token .Pos , string )	if  p .mode &DeclarationErrors  != 0  {		declErr  = p .error 	}	if  p .mode &SkipObjectResolution  == 0  {		resolveFile (f , p .file , declErr )	}	return  f }func  packIndexExpr(x  ast .Expr , lbrack  token .Pos , exprs  []ast .Expr , rbrack  token .Pos ) ast .Expr  {	switch  len (exprs ) {	case  0 :		panic ("internal error: packIndexExpr with empty expr slice" )	case  1 :		return  &ast .IndexExpr {			X :      x ,			Lbrack : lbrack ,			Index :  exprs [0 ],			Rbrack : rbrack ,		}	default :		return  &ast .IndexListExpr {			X :       x ,			Lbrack :  lbrack ,			Indices : exprs ,			Rbrack :  rbrack ,		}	}} The pages are generated with Golds v0.7.9-preview . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101  (reachable from the left QR code) to get the latest news of Golds .