1package js
   2
   3import (
   4	"bytes"
   5	"errors"
   6	"fmt"
   7	"io"
   8
   9	"github.com/tdewolff/parse/v2"
  10	"github.com/tdewolff/parse/v2/buffer"
  11)
  12
  13type Options struct {
  14	WhileToFor bool
  15}
  16
  17// Parser is the state for the parser.
  18type Parser struct {
  19	l   *Lexer
  20	o   Options
  21	err error
  22
  23	data                   []byte
  24	tt                     TokenType
  25	prevLT                 bool
  26	inFor                  bool
  27	await, yield           bool
  28	assumeArrowFunc        bool
  29	allowDirectivePrologue bool
  30
  31	stmtLevel int
  32	exprLevel int
  33
  34	scope *Scope
  35}
  36
  37// Parse returns a JS AST tree of.
  38func Parse(r *parse.Input, o Options) (*AST, error) {
  39	ast := &AST{}
  40	p := &Parser{
  41		l:     NewLexer(r),
  42		o:     o,
  43		tt:    WhitespaceToken, // trick so that next() works
  44		await: true,
  45	}
  46
  47	// process shebang
  48	if r.Peek(0) == '#' && r.Peek(1) == '!' {
  49		r.Move(2)
  50		p.l.consumeSingleLineComment() // consume till end-of-line
  51		ast.Comments = append(ast.Comments, r.Shift())
  52	}
  53
  54	p.tt, p.data = p.l.Next()
  55	for p.tt == CommentToken || p.tt == CommentLineTerminatorToken {
  56		ast.Comments = append(ast.Comments, p.data)
  57		p.tt, p.data = p.l.Next()
  58		if p.tt == WhitespaceToken || p.tt == LineTerminatorToken {
  59			p.tt, p.data = p.l.Next()
  60		}
  61	}
  62	if p.tt == WhitespaceToken || p.tt == LineTerminatorToken {
  63		p.next()
  64	}
  65	// prevLT may be wrong but that is not a problem
  66	ast.BlockStmt = p.parseModule()
  67
  68	if p.err == nil {
  69		p.err = p.l.Err()
  70	} else {
  71		offset := p.l.r.Offset() - len(p.data)
  72		p.err = parse.NewError(buffer.NewReader(p.l.r.Bytes()), offset, p.err.Error())
  73	}
  74	if p.err == io.EOF {
  75		p.err = nil
  76	}
  77	return ast, p.err
  78}
  79
  80////////////////////////////////////////////////////////////////
  81
  82func (p *Parser) next() {
  83	p.prevLT = false
  84	p.tt, p.data = p.l.Next()
  85	for p.tt == WhitespaceToken || p.tt == LineTerminatorToken || p.tt == CommentToken || p.tt == CommentLineTerminatorToken {
  86		if p.tt == LineTerminatorToken || p.tt == CommentLineTerminatorToken {
  87			p.prevLT = true
  88		}
  89		p.tt, p.data = p.l.Next()
  90	}
  91}
  92
  93func (p *Parser) failMessage(msg string, args ...interface{}) {
  94	if p.err == nil {
  95		p.err = fmt.Errorf(msg, args...)
  96		p.tt = ErrorToken
  97	}
  98}
  99
 100func (p *Parser) fail(in string, expected ...TokenType) {
 101	if p.err == nil {
 102		msg := "unexpected"
 103		if 0 < len(expected) {
 104			msg = "expected"
 105			for i, tt := range expected[:len(expected)-1] {
 106				if 0 < i {
 107					msg += ","
 108				}
 109				msg += " " + tt.String() + ""
 110			}
 111			if 2 < len(expected) {
 112				msg += ", or"
 113			} else if 1 < len(expected) {
 114				msg += " or"
 115			}
 116			msg += " " + expected[len(expected)-1].String() + " instead of"
 117		}
 118
 119		if p.tt == ErrorToken {
 120			if p.l.Err() == io.EOF {
 121				msg += " EOF"
 122			} else if lexerErr, ok := p.l.Err().(*parse.Error); ok {
 123				msg = lexerErr.Message
 124			} else {
 125				// does not happen
 126			}
 127		} else {
 128			msg += " " + string(p.data) + ""
 129		}
 130		if in != "" {
 131			msg += " in " + in
 132		}
 133
 134		p.err = errors.New(msg)
 135		p.tt = ErrorToken
 136	}
 137}
 138
 139func (p *Parser) consume(in string, tt TokenType) bool {
 140	if p.tt != tt {
 141		p.fail(in, tt)
 142		return false
 143	}
 144	p.next()
 145	return true
 146}
 147
 148// TODO: refactor
 149//type ScopeState struct {
 150//	scope           *Scope
 151//	async           bool
 152//	generator       bool
 153//	assumeArrowFunc bool
 154//}
 155
 156func (p *Parser) enterScope(scope *Scope, isFunc bool) *Scope {
 157	// create a new scope object and add it to the parent
 158	parent := p.scope
 159	p.scope = scope
 160	*scope = Scope{
 161		Parent: parent,
 162	}
 163	if isFunc {
 164		scope.Func = scope
 165	} else if parent != nil {
 166		scope.Func = parent.Func
 167	}
 168	return parent
 169}
 170
 171func (p *Parser) exitScope(parent *Scope) {
 172	p.scope.HoistUndeclared()
 173	p.scope = parent
 174}
 175
 176func (p *Parser) parseModule() (module BlockStmt) {
 177	p.enterScope(&module.Scope, true)
 178	p.allowDirectivePrologue = true
 179	for {
 180		switch p.tt {
 181		case ErrorToken:
 182			return
 183		case ImportToken:
 184			p.next()
 185			if p.tt == OpenParenToken {
 186				// could be an import call expression
 187				left := &LiteralExpr{ImportToken, []byte("import")}
 188				p.exprLevel++
 189				suffix := p.parseExpressionSuffix(left, OpExpr, OpCall)
 190				p.exprLevel--
 191				module.List = append(module.List, &ExprStmt{suffix})
 192			} else {
 193				importStmt := p.parseImportStmt()
 194				module.List = append(module.List, &importStmt)
 195			}
 196		case ExportToken:
 197			exportStmt := p.parseExportStmt()
 198			module.List = append(module.List, &exportStmt)
 199		default:
 200			module.List = append(module.List, p.parseStmt(true))
 201		}
 202	}
 203}
 204
 205func (p *Parser) parseStmt(allowDeclaration bool) (stmt IStmt) {
 206	p.stmtLevel++
 207	if 1000 < p.stmtLevel {
 208		p.failMessage("too many nested statements")
 209		return nil
 210	}
 211
 212	allowDirectivePrologue := p.allowDirectivePrologue
 213	p.allowDirectivePrologue = false
 214
 215	switch tt := p.tt; tt {
 216	case OpenBraceToken:
 217		stmt = p.parseBlockStmt("block statement")
 218	case ConstToken, VarToken:
 219		if !allowDeclaration && tt == ConstToken {
 220			p.fail("statement")
 221			return
 222		}
 223		p.next()
 224		varDecl := p.parseVarDecl(tt, true)
 225		stmt = varDecl
 226		if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 227			if tt == ConstToken {
 228				p.fail("const declaration")
 229			} else {
 230				p.fail("var statement")
 231			}
 232			return
 233		}
 234	case LetToken:
 235		let := p.data
 236		p.next()
 237		if allowDeclaration && (IsIdentifier(p.tt) || p.tt == YieldToken || p.tt == AwaitToken || p.tt == OpenBracketToken || p.tt == OpenBraceToken) {
 238			stmt = p.parseVarDecl(tt, false)
 239			if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 240				p.fail("let declaration")
 241				return
 242			}
 243		} else {
 244			// expression
 245			stmt = &ExprStmt{p.parseIdentifierExpression(OpExpr, let)}
 246			if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 247				p.fail("expression")
 248				return
 249			}
 250		}
 251	case IfToken:
 252		p.next()
 253		if !p.consume("if statement", OpenParenToken) {
 254			return
 255		}
 256		cond := p.parseExpression(OpExpr)
 257		if !p.consume("if statement", CloseParenToken) {
 258			return
 259		}
 260		body := p.parseStmt(false)
 261
 262		var elseBody IStmt
 263		if p.tt == ElseToken {
 264			p.next()
 265			elseBody = p.parseStmt(false)
 266		}
 267		stmt = &IfStmt{cond, body, elseBody}
 268	case ContinueToken, BreakToken:
 269		tt := p.tt
 270		p.next()
 271		var label []byte
 272		if !p.prevLT && p.isIdentifierReference(p.tt) {
 273			label = p.data
 274			p.next()
 275		}
 276		stmt = &BranchStmt{tt, label}
 277	case ReturnToken:
 278		p.next()
 279		var value IExpr
 280		if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 281			value = p.parseExpression(OpExpr)
 282		}
 283		stmt = &ReturnStmt{value}
 284	case WithToken:
 285		p.next()
 286		if !p.consume("with statement", OpenParenToken) {
 287			return
 288		}
 289		cond := p.parseExpression(OpExpr)
 290		if !p.consume("with statement", CloseParenToken) {
 291			return
 292		}
 293
 294		p.scope.Func.HasWith = true
 295		stmt = &WithStmt{cond, p.parseStmt(false)}
 296	case DoToken:
 297		stmt = &DoWhileStmt{}
 298		p.next()
 299		body := p.parseStmt(false)
 300		if !p.consume("do-while statement", WhileToken) {
 301			return
 302		}
 303		if !p.consume("do-while statement", OpenParenToken) {
 304			return
 305		}
 306		stmt = &DoWhileStmt{p.parseExpression(OpExpr), body}
 307		if !p.consume("do-while statement", CloseParenToken) {
 308			return
 309		}
 310	case WhileToken:
 311		p.next()
 312		if !p.consume("while statement", OpenParenToken) {
 313			return
 314		}
 315		cond := p.parseExpression(OpExpr)
 316		if !p.consume("while statement", CloseParenToken) {
 317			return
 318		}
 319		body := p.parseStmt(false)
 320		if p.o.WhileToFor {
 321			varDecl := &VarDecl{TokenType: VarToken, Scope: p.scope, InFor: true}
 322			p.scope.Func.VarDecls = append(p.scope.Func.VarDecls, varDecl)
 323
 324			block, ok := body.(*BlockStmt)
 325			if !ok {
 326				block = &BlockStmt{List: []IStmt{body}}
 327			}
 328			stmt = &ForStmt{varDecl, cond, nil, block}
 329		} else {
 330			stmt = &WhileStmt{cond, body}
 331		}
 332	case ForToken:
 333		p.next()
 334		await := p.await && p.tt == AwaitToken
 335		if await {
 336			p.next()
 337		}
 338		if !p.consume("for statement", OpenParenToken) {
 339			return
 340		}
 341
 342		body := &BlockStmt{}
 343		parent := p.enterScope(&body.Scope, false)
 344
 345		var init IExpr
 346		p.inFor = true
 347		if p.tt == VarToken || p.tt == LetToken || p.tt == ConstToken {
 348			tt := p.tt
 349			p.next()
 350			varDecl := p.parseVarDecl(tt, true)
 351			if p.tt != SemicolonToken && (1 < len(varDecl.List) || varDecl.List[0].Default != nil) {
 352				p.fail("for statement")
 353				return
 354			} else if p.tt == SemicolonToken && varDecl.List[0].Default == nil {
 355				// all but the first item were already verified
 356				if _, ok := varDecl.List[0].Binding.(*Var); !ok {
 357					p.fail("for statement")
 358					return
 359				}
 360			}
 361			init = varDecl
 362		} else if p.tt != SemicolonToken {
 363			init = p.parseExpression(OpExpr)
 364		}
 365		p.inFor = false
 366
 367		if p.tt == SemicolonToken {
 368			var cond, post IExpr
 369			if await {
 370				p.fail("for statement", OfToken)
 371				return
 372			}
 373			p.next()
 374			if p.tt != SemicolonToken {
 375				cond = p.parseExpression(OpExpr)
 376			}
 377			if !p.consume("for statement", SemicolonToken) {
 378				return
 379			}
 380			if p.tt != CloseParenToken {
 381				post = p.parseExpression(OpExpr)
 382			}
 383			if !p.consume("for statement", CloseParenToken) {
 384				return
 385			}
 386			p.scope.MarkForStmt()
 387			if p.tt == OpenBraceToken {
 388				body.List = p.parseStmtList("")
 389			} else if p.tt != SemicolonToken {
 390				body.List = []IStmt{p.parseStmt(false)}
 391			}
 392			if init == nil {
 393				varDecl := &VarDecl{TokenType: VarToken, Scope: p.scope, InFor: true}
 394				p.scope.Func.VarDecls = append(p.scope.Func.VarDecls, varDecl)
 395				init = varDecl
 396			} else if varDecl, ok := init.(*VarDecl); ok {
 397				varDecl.InFor = true
 398			}
 399			stmt = &ForStmt{init, cond, post, body}
 400		} else if p.tt == InToken {
 401			if await {
 402				p.fail("for statement", OfToken)
 403				return
 404			}
 405			p.next()
 406			value := p.parseExpression(OpExpr)
 407			if !p.consume("for statement", CloseParenToken) {
 408				return
 409			}
 410			p.scope.MarkForStmt()
 411			if p.tt == OpenBraceToken {
 412				body.List = p.parseStmtList("")
 413			} else if p.tt != SemicolonToken {
 414				body.List = []IStmt{p.parseStmt(false)}
 415			}
 416			if varDecl, ok := init.(*VarDecl); ok {
 417				varDecl.InForInOf = true
 418			}
 419			stmt = &ForInStmt{init, value, body}
 420		} else if p.tt == OfToken {
 421			p.next()
 422			value := p.parseExpression(OpAssign)
 423			if !p.consume("for statement", CloseParenToken) {
 424				return
 425			}
 426			p.scope.MarkForStmt()
 427			if p.tt == OpenBraceToken {
 428				body.List = p.parseStmtList("")
 429			} else if p.tt != SemicolonToken {
 430				body.List = []IStmt{p.parseStmt(false)}
 431			}
 432			if varDecl, ok := init.(*VarDecl); ok {
 433				varDecl.InForInOf = true
 434			}
 435			stmt = &ForOfStmt{await, init, value, body}
 436		} else {
 437			p.fail("for statement", InToken, OfToken, SemicolonToken)
 438			return
 439		}
 440		p.exitScope(parent)
 441	case SwitchToken:
 442		p.next()
 443		if !p.consume("switch statement", OpenParenToken) {
 444			return
 445		}
 446		init := p.parseExpression(OpExpr)
 447		if !p.consume("switch statement", CloseParenToken) {
 448			return
 449		}
 450
 451		// case block
 452		if !p.consume("switch statement", OpenBraceToken) {
 453			return
 454		}
 455
 456		switchStmt := &SwitchStmt{Init: init}
 457		parent := p.enterScope(&switchStmt.Scope, false)
 458		for {
 459			if p.tt == ErrorToken {
 460				p.fail("switch statement")
 461				return
 462			} else if p.tt == CloseBraceToken {
 463				p.next()
 464				break
 465			}
 466
 467			clause := p.tt
 468			var list IExpr
 469			if p.tt == CaseToken {
 470				p.next()
 471				list = p.parseExpression(OpExpr)
 472			} else if p.tt == DefaultToken {
 473				p.next()
 474			} else {
 475				p.fail("switch statement", CaseToken, DefaultToken)
 476				return
 477			}
 478			if !p.consume("switch statement", ColonToken) {
 479				return
 480			}
 481
 482			var stmts []IStmt
 483			for p.tt != CaseToken && p.tt != DefaultToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 484				stmts = append(stmts, p.parseStmt(true))
 485			}
 486			switchStmt.List = append(switchStmt.List, CaseClause{clause, list, stmts})
 487		}
 488		p.exitScope(parent)
 489		stmt = switchStmt
 490	case FunctionToken:
 491		if !allowDeclaration {
 492			p.fail("statement")
 493			return
 494		}
 495		stmt = p.parseFuncDecl()
 496	case AsyncToken: // async function
 497		if !allowDeclaration {
 498			p.fail("statement")
 499			return
 500		}
 501		async := p.data
 502		p.next()
 503		if p.tt == FunctionToken && !p.prevLT {
 504			stmt = p.parseAsyncFuncDecl()
 505		} else {
 506			// expression
 507			stmt = &ExprStmt{p.parseAsyncExpression(OpExpr, async)}
 508			if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 509				p.fail("expression")
 510				return
 511			}
 512		}
 513	case ClassToken:
 514		if !allowDeclaration {
 515			p.fail("statement")
 516			return
 517		}
 518		stmt = p.parseClassDecl()
 519	case ThrowToken:
 520		p.next()
 521		var value IExpr
 522		if !p.prevLT {
 523			value = p.parseExpression(OpExpr)
 524		}
 525		stmt = &ThrowStmt{value}
 526	case TryToken:
 527		p.next()
 528		body := p.parseBlockStmt("try statement")
 529		var binding IBinding
 530		var catch, finally *BlockStmt
 531		if p.tt == CatchToken {
 532			p.next()
 533			catch = &BlockStmt{}
 534			parent := p.enterScope(&catch.Scope, false)
 535			if p.tt == OpenParenToken {
 536				p.next()
 537				binding = p.parseBinding(CatchDecl) // local to block scope of catch
 538				if !p.consume("try-catch statement", CloseParenToken) {
 539					return
 540				}
 541			}
 542			catch.List = p.parseStmtList("try-catch statement")
 543			p.exitScope(parent)
 544		} else if p.tt != FinallyToken {
 545			p.fail("try statement", CatchToken, FinallyToken)
 546			return
 547		}
 548		if p.tt == FinallyToken {
 549			p.next()
 550			finally = p.parseBlockStmt("try-finally statement")
 551		}
 552		stmt = &TryStmt{body, binding, catch, finally}
 553	case DebuggerToken:
 554		p.next()
 555		stmt = &DebuggerStmt{}
 556	case SemicolonToken, ErrorToken:
 557		stmt = &EmptyStmt{}
 558	default:
 559		if p.isIdentifierReference(p.tt) {
 560			// labelled statement or expression
 561			label := p.data
 562			p.next()
 563			if p.tt == ColonToken {
 564				p.next()
 565				stmt = &LabelledStmt{label, p.parseStmt(true)} // allows illegal async function, generator function, let, const, or class declarations
 566			} else {
 567				// expression
 568				stmt = &ExprStmt{p.parseIdentifierExpression(OpExpr, label)}
 569				if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 570					p.fail("expression")
 571					return
 572				}
 573			}
 574		} else {
 575			// expression
 576			stmt = &ExprStmt{p.parseExpression(OpExpr)}
 577			if !p.prevLT && p.tt != SemicolonToken && p.tt != CloseBraceToken && p.tt != ErrorToken {
 578				p.fail("expression")
 579				return
 580			} else if lit, ok := stmt.(*ExprStmt).Value.(*LiteralExpr); ok && allowDirectivePrologue && lit.TokenType == StringToken && len(lit.Data) == 12 && bytes.Equal(lit.Data[1:11], []byte("use strict")) {
 581				stmt = &DirectivePrologueStmt{lit.Data}
 582				p.allowDirectivePrologue = true
 583			}
 584		}
 585	}
 586	if p.tt == SemicolonToken {
 587		p.next()
 588	}
 589	p.stmtLevel--
 590	return
 591}
 592
 593func (p *Parser) parseStmtList(in string) (list []IStmt) {
 594	if !p.consume(in, OpenBraceToken) {
 595		return
 596	}
 597	for {
 598		if p.tt == ErrorToken {
 599			p.fail("")
 600			return
 601		} else if p.tt == CloseBraceToken {
 602			p.next()
 603			break
 604		}
 605		list = append(list, p.parseStmt(true))
 606	}
 607	return
 608}
 609
 610func (p *Parser) parseBlockStmt(in string) (blockStmt *BlockStmt) {
 611	blockStmt = &BlockStmt{}
 612	parent := p.enterScope(&blockStmt.Scope, false)
 613	blockStmt.List = p.parseStmtList(in)
 614	p.exitScope(parent)
 615	return
 616}
 617
 618func (p *Parser) parseImportStmt() (importStmt ImportStmt) {
 619	// assume we're passed import
 620	if p.tt == StringToken {
 621		importStmt.Module = p.data
 622		p.next()
 623	} else {
 624		if IsIdentifier(p.tt) || p.tt == YieldToken {
 625			importStmt.Default = p.data
 626			p.next()
 627			if p.tt == CommaToken {
 628				p.next()
 629			}
 630		}
 631		if p.tt == MulToken {
 632			star := p.data
 633			p.next()
 634			if !p.consume("import statement", AsToken) {
 635				return
 636			}
 637			if !IsIdentifier(p.tt) && p.tt != YieldToken {
 638				p.fail("import statement", IdentifierToken)
 639				return
 640			}
 641			importStmt.List = []Alias{Alias{star, p.data}}
 642			p.next()
 643		} else if p.tt == OpenBraceToken {
 644			p.next()
 645			for IsIdentifierName(p.tt) || p.tt == StringToken {
 646				tt := p.tt
 647				var name, binding []byte = nil, p.data
 648				p.next()
 649				if p.tt == AsToken {
 650					p.next()
 651					if !IsIdentifier(p.tt) && p.tt != YieldToken {
 652						p.fail("import statement", IdentifierToken)
 653						return
 654					}
 655					name = binding
 656					binding = p.data
 657					p.next()
 658				} else if !IsIdentifier(tt) && tt != YieldToken || tt == StringToken {
 659					p.fail("import statement", IdentifierToken, StringToken)
 660					return
 661				}
 662				importStmt.List = append(importStmt.List, Alias{name, binding})
 663				if p.tt == CommaToken {
 664					p.next()
 665					if p.tt == CloseBraceToken {
 666						importStmt.List = append(importStmt.List, Alias{})
 667						break
 668					}
 669				}
 670			}
 671			if !p.consume("import statement", CloseBraceToken) {
 672				return
 673			}
 674		}
 675		if importStmt.Default == nil && len(importStmt.List) == 0 {
 676			p.fail("import statement", StringToken, IdentifierToken, MulToken, OpenBraceToken)
 677			return
 678		}
 679
 680		if !p.consume("import statement", FromToken) {
 681			return
 682		}
 683		if p.tt != StringToken {
 684			p.fail("import statement", StringToken)
 685			return
 686		}
 687		importStmt.Module = p.data
 688		p.next()
 689	}
 690	if p.tt == SemicolonToken {
 691		p.next()
 692	}
 693	return
 694}
 695
 696func (p *Parser) parseExportStmt() (exportStmt ExportStmt) {
 697	// assume we're at export
 698	p.next()
 699	if p.tt == MulToken || p.tt == OpenBraceToken {
 700		if p.tt == MulToken {
 701			star := p.data
 702			p.next()
 703			if p.tt == AsToken {
 704				p.next()
 705				if !IsIdentifierName(p.tt) && p.tt != StringToken {
 706					p.fail("export statement", IdentifierToken, StringToken)
 707					return
 708				}
 709				exportStmt.List = []Alias{Alias{star, p.data}}
 710				p.next()
 711			} else {
 712				exportStmt.List = []Alias{Alias{nil, star}}
 713			}
 714			if p.tt != FromToken {
 715				p.fail("export statement", FromToken)
 716				return
 717			}
 718		} else {
 719			p.next()
 720			for IsIdentifierName(p.tt) || p.tt == StringToken {
 721				var name, binding []byte = nil, p.data
 722				p.next()
 723				if p.tt == AsToken {
 724					p.next()
 725					if !IsIdentifierName(p.tt) && p.tt != StringToken {
 726						p.fail("export statement", IdentifierToken, StringToken)
 727						return
 728					}
 729					name = binding
 730					binding = p.data
 731					p.next()
 732				}
 733				exportStmt.List = append(exportStmt.List, Alias{name, binding})
 734				if p.tt == CommaToken {
 735					p.next()
 736					if p.tt == CloseBraceToken {
 737						exportStmt.List = append(exportStmt.List, Alias{})
 738						break
 739					}
 740				}
 741			}
 742			if !p.consume("export statement", CloseBraceToken) {
 743				return
 744			}
 745		}
 746		if p.tt == FromToken {
 747			p.next()
 748			if p.tt != StringToken {
 749				p.fail("export statement", StringToken)
 750				return
 751			}
 752			exportStmt.Module = p.data
 753			p.next()
 754		}
 755	} else if p.tt == VarToken || p.tt == ConstToken || p.tt == LetToken {
 756		tt := p.tt
 757		p.next()
 758		exportStmt.Decl = p.parseVarDecl(tt, false)
 759	} else if p.tt == FunctionToken {
 760		exportStmt.Decl = p.parseFuncDecl()
 761	} else if p.tt == AsyncToken { // async function
 762		p.next()
 763		if p.tt != FunctionToken || p.prevLT {
 764			p.fail("export statement", FunctionToken)
 765			return
 766		}
 767		exportStmt.Decl = p.parseAsyncFuncDecl()
 768	} else if p.tt == ClassToken {
 769		exportStmt.Decl = p.parseClassDecl()
 770	} else if p.tt == DefaultToken {
 771		exportStmt.Default = true
 772		p.next()
 773		if p.tt == FunctionToken {
 774			exportStmt.Decl = p.parseFuncDeclDefault()
 775		} else if p.tt == AsyncToken { // async function or async arrow function
 776			async := p.data
 777			p.next()
 778			if p.tt == FunctionToken && !p.prevLT {
 779				exportStmt.Decl = p.parseAsyncFuncDeclDefault()
 780			} else {
 781				// expression
 782				exportStmt.Decl = p.parseAsyncExpression(OpExpr, async)
 783			}
 784		} else if p.tt == ClassToken {
 785			exportStmt.Decl = p.parseClassDeclDefault()
 786		} else {
 787			exportStmt.Decl = p.parseExpression(OpAssign)
 788		}
 789	} else {
 790		p.fail("export statement", MulToken, OpenBraceToken, VarToken, LetToken, ConstToken, FunctionToken, AsyncToken, ClassToken, DefaultToken)
 791		return
 792	}
 793	if p.tt == SemicolonToken {
 794		p.next()
 795	}
 796	return
 797}
 798
 799func (p *Parser) parseVarDecl(tt TokenType, canBeHoisted bool) (varDecl *VarDecl) {
 800	// assume we're past var, let or const
 801	varDecl = &VarDecl{
 802		TokenType: tt,
 803		Scope:     p.scope,
 804	}
 805	declType := LexicalDecl
 806	if tt == VarToken {
 807		declType = VariableDecl
 808		if canBeHoisted {
 809			p.scope.Func.VarDecls = append(p.scope.Func.VarDecls, varDecl)
 810		}
 811	}
 812	for {
 813		// binding element, var declaration in for-in or for-of can never have a default
 814		var bindingElement BindingElement
 815		parentInFor := p.inFor
 816		p.inFor = false
 817		bindingElement.Binding = p.parseBinding(declType)
 818		p.inFor = parentInFor
 819		if p.tt == EqToken {
 820			p.next()
 821			bindingElement.Default = p.parseExpression(OpAssign)
 822		} else if _, ok := bindingElement.Binding.(*Var); !ok && (!p.inFor || 0 < len(varDecl.List)) {
 823			p.fail("var statement", EqToken)
 824			return
 825		} else if tt == ConstToken && (!p.inFor || p.inFor && p.tt != OfToken && p.tt != InToken) {
 826			p.fail("const statement", EqToken)
 827		}
 828
 829		varDecl.List = append(varDecl.List, bindingElement)
 830		if p.tt == CommaToken {
 831			p.next()
 832		} else {
 833			break
 834		}
 835	}
 836	return
 837}
 838
 839func (p *Parser) parseFuncParams(in string) (params Params) {
 840	if !p.consume(in, OpenParenToken) {
 841		return
 842	}
 843
 844	for p.tt != CloseParenToken && p.tt != ErrorToken {
 845		if p.tt == EllipsisToken {
 846			// binding rest element
 847			p.next()
 848			params.Rest = p.parseBinding(ArgumentDecl)
 849			p.consume(in, CloseParenToken)
 850			return
 851		}
 852		params.List = append(params.List, p.parseBindingElement(ArgumentDecl))
 853		if p.tt != CommaToken {
 854			break
 855		}
 856		p.next()
 857	}
 858	if p.tt != CloseParenToken {
 859		p.fail(in)
 860		return
 861	}
 862	p.next()
 863
 864	// mark undeclared vars as arguments in `function f(a=b){var b}` where the b's are different vars
 865	p.scope.MarkFuncArgs()
 866	return
 867}
 868
 869func (p *Parser) parseFuncDecl() (funcDecl *FuncDecl) {
 870	return p.parseAnyFunc(false, false, false)
 871}
 872
 873func (p *Parser) parseFuncDeclDefault() (funcDecl *FuncDecl) {
 874	return p.parseAnyFunc(false, true, false)
 875}
 876
 877func (p *Parser) parseAsyncFuncDecl() (funcDecl *FuncDecl) {
 878	return p.parseAnyFunc(true, false, false)
 879}
 880
 881func (p *Parser) parseAsyncFuncDeclDefault() (funcDecl *FuncDecl) {
 882	return p.parseAnyFunc(true, true, false)
 883}
 884
 885func (p *Parser) parseFuncExpr() (funcDecl *FuncDecl) {
 886	return p.parseAnyFunc(false, false, true)
 887}
 888
 889func (p *Parser) parseAsyncFuncExpr() (funcDecl *FuncDecl) {
 890	return p.parseAnyFunc(true, false, true)
 891}
 892
 893func (p *Parser) parseAnyFunc(async, exportDefault, expr bool) (funcDecl *FuncDecl) {
 894	// assume we're at function
 895	p.next()
 896	funcDecl = &FuncDecl{}
 897	funcDecl.Async = async
 898	funcDecl.Generator = p.tt == MulToken
 899	if funcDecl.Generator {
 900		p.next()
 901	}
 902	var ok bool
 903	var name []byte
 904	if expr && (IsIdentifier(p.tt) || p.tt == YieldToken || p.tt == AwaitToken) || !expr && p.isIdentifierReference(p.tt) {
 905		name = p.data
 906		if !expr {
 907			funcDecl.Name, ok = p.scope.Declare(FunctionDecl, p.data)
 908			if !ok {
 909				p.failMessage("identifier %s has already been declared", string(p.data))
 910				return
 911			}
 912		}
 913		p.next()
 914	} else if !expr && !exportDefault {
 915		p.fail("function declaration", IdentifierToken)
 916		return
 917	} else if p.tt != OpenParenToken {
 918		p.fail("function declaration", IdentifierToken, OpenParenToken)
 919		return
 920	}
 921	parent := p.enterScope(&funcDecl.Body.Scope, true)
 922	parentAwait, parentYield := p.await, p.yield
 923	p.await, p.yield = funcDecl.Async, funcDecl.Generator
 924
 925	if expr && name != nil {
 926		funcDecl.Name, _ = p.scope.Declare(ExprDecl, name) // cannot fail
 927	}
 928	funcDecl.Params = p.parseFuncParams("function declaration")
 929	p.allowDirectivePrologue = true
 930	funcDecl.Body.List = p.parseStmtList("function declaration")
 931
 932	p.await, p.yield = parentAwait, parentYield
 933	p.exitScope(parent)
 934	return
 935}
 936
 937func (p *Parser) parseClassDecl() (classDecl *ClassDecl) {
 938	return p.parseAnyClass(false, false)
 939}
 940
 941func (p *Parser) parseClassDeclDefault() (classDecl *ClassDecl) {
 942	return p.parseAnyClass(true, false)
 943}
 944
 945func (p *Parser) parseClassExpr() (classDecl *ClassDecl) {
 946	return p.parseAnyClass(false, true)
 947}
 948
 949func (p *Parser) parseAnyClass(exportDefault, expr bool) (classDecl *ClassDecl) {
 950	// assume we're at class
 951	p.next()
 952	classDecl = &ClassDecl{}
 953	if IsIdentifier(p.tt) || p.tt == YieldToken || p.tt == AwaitToken {
 954		if !expr {
 955			var ok bool
 956			classDecl.Name, ok = p.scope.Declare(LexicalDecl, p.data)
 957			if !ok {
 958				p.failMessage("identifier %s has already been declared", string(p.data))
 959				return
 960			}
 961		} else {
 962			//classDecl.Name, ok = p.scope.Declare(ExprDecl, p.data) // classes do not register vars
 963			classDecl.Name = &Var{p.data, nil, 1, ExprDecl}
 964		}
 965		p.next()
 966	} else if !expr && !exportDefault {
 967		p.fail("class declaration", IdentifierToken)
 968		return
 969	}
 970	if p.tt == ExtendsToken {
 971		p.next()
 972		classDecl.Extends = p.parseExpression(OpLHS)
 973	}
 974
 975	if !p.consume("class declaration", OpenBraceToken) {
 976		return
 977	}
 978	for {
 979		if p.tt == ErrorToken {
 980			p.fail("class declaration")
 981			return
 982		} else if p.tt == SemicolonToken {
 983			p.next()
 984			continue
 985		} else if p.tt == CloseBraceToken {
 986			p.next()
 987			break
 988		}
 989
 990		classDecl.List = append(classDecl.List, p.parseClassElement())
 991	}
 992	return
 993}
 994
 995func (p *Parser) parseClassElement() ClassElement {
 996	method := &MethodDecl{}
 997	var data []byte // either static, async, get, or set
 998	if p.tt == StaticToken {
 999		method.Static = true
1000		data = p.data
1001		p.next()
1002		if p.tt == OpenBraceToken {
1003			return ClassElement{StaticBlock: p.parseBlockStmt("class static block")}
1004		}
1005	}
1006	if p.tt == MulToken {
1007		method.Generator = true
1008		p.next()
1009	} else if p.tt == AsyncToken {
1010		data = p.data
1011		p.next()
1012		if !p.prevLT {
1013			method.Async = true
1014			if p.tt == MulToken {
1015				method.Generator = true
1016				data = nil
1017				p.next()
1018			}
1019		}
1020	} else if p.tt == GetToken {
1021		method.Get = true
1022		data = p.data
1023		p.next()
1024	} else if p.tt == SetToken {
1025		method.Set = true
1026		data = p.data
1027		p.next()
1028	}
1029
1030	isField := false
1031	if data != nil && p.tt == OpenParenToken {
1032		// (static) method name is: static, async, get, or set
1033		method.Name.Literal = LiteralExpr{IdentifierToken, data}
1034		if method.Async || method.Get || method.Set {
1035			method.Async = false
1036			method.Get = false
1037			method.Set = false
1038		} else {
1039			method.Static = false
1040		}
1041	} else if data != nil && (p.tt == EqToken || p.tt == SemicolonToken || p.tt == CloseBraceToken) {
1042		// (static) field name is: static, async, get, or set
1043		method.Name.Literal = LiteralExpr{IdentifierToken, data}
1044		if !method.Async && !method.Get && !method.Set {
1045			method.Static = false
1046		}
1047		isField = true
1048	} else {
1049		if p.tt == PrivateIdentifierToken {
1050			method.Name.Literal = LiteralExpr{p.tt, p.data}
1051			p.next()
1052		} else {
1053			method.Name = p.parsePropertyName("method or field definition")
1054		}
1055		if (data == nil || method.Static) && p.tt != OpenParenToken {
1056			isField = true
1057		}
1058	}
1059
1060	if isField {
1061		var init IExpr
1062		if p.tt == EqToken {
1063			p.next()
1064			init = p.parseExpression(OpAssign)
1065		}
1066		return ClassElement{Field: Field{Static: method.Static, Name: method.Name, Init: init}}
1067	}
1068
1069	parent := p.enterScope(&method.Body.Scope, true)
1070	parentAwait, parentYield := p.await, p.yield
1071	p.await, p.yield = method.Async, method.Generator
1072
1073	method.Params = p.parseFuncParams("method definition")
1074	p.allowDirectivePrologue = true
1075	method.Body.List = p.parseStmtList("method definition")
1076
1077	p.await, p.yield = parentAwait, parentYield
1078	p.exitScope(parent)
1079	return ClassElement{Method: method}
1080}
1081
1082func (p *Parser) parsePropertyName(in string) (propertyName PropertyName) {
1083	if IsIdentifierName(p.tt) {
1084		propertyName.Literal = LiteralExpr{IdentifierToken, p.data}
1085		p.next()
1086	} else if p.tt == StringToken {
1087		// reinterpret string as identifier or number if we can, except for empty strings
1088		if isIdent := AsIdentifierName(p.data[1 : len(p.data)-1]); isIdent {
1089			propertyName.Literal = LiteralExpr{IdentifierToken, p.data[1 : len(p.data)-1]}
1090		} else if isNum := AsDecimalLiteral(p.data[1 : len(p.data)-1]); isNum {
1091			propertyName.Literal = LiteralExpr{DecimalToken, p.data[1 : len(p.data)-1]}
1092		} else {
1093			propertyName.Literal = LiteralExpr{p.tt, p.data}
1094		}
1095		p.next()
1096	} else if IsNumeric(p.tt) {
1097		propertyName.Literal = LiteralExpr{p.tt, p.data}
1098		p.next()
1099	} else if p.tt == OpenBracketToken {
1100		p.next()
1101		propertyName.Computed = p.parseExpression(OpAssign)
1102		if !p.consume(in, CloseBracketToken) {
1103			return
1104		}
1105	} else {
1106		p.fail(in, IdentifierToken, StringToken, NumericToken, OpenBracketToken)
1107		return
1108	}
1109	return
1110}
1111
1112func (p *Parser) parseBindingElement(decl DeclType) (bindingElement BindingElement) {
1113	// binding element
1114	bindingElement.Binding = p.parseBinding(decl)
1115	if p.tt == EqToken {
1116		p.next()
1117		bindingElement.Default = p.parseExpression(OpAssign)
1118	}
1119	return
1120}
1121
1122func (p *Parser) parseBinding(decl DeclType) (binding IBinding) {
1123	// binding identifier or binding pattern
1124	if p.isIdentifierReference(p.tt) {
1125		var ok bool
1126		binding, ok = p.scope.Declare(decl, p.data)
1127		if !ok {
1128			p.failMessage("identifier %s has already been declared", string(p.data))
1129			return
1130		}
1131		p.next()
1132	} else if p.tt == OpenBracketToken {
1133		p.next()
1134		array := BindingArray{}
1135		if p.tt == CommaToken {
1136			array.List = append(array.List, BindingElement{})
1137		}
1138		last := 0
1139		for p.tt != CloseBracketToken {
1140			// elision
1141			for p.tt == CommaToken {
1142				p.next()
1143				if p.tt == CommaToken {
1144					array.List = append(array.List, BindingElement{})
1145				}
1146			}
1147			// binding rest element
1148			if p.tt == EllipsisToken {
1149				p.next()
1150				array.Rest = p.parseBinding(decl)
1151				if p.tt != CloseBracketToken {
1152					p.fail("array binding pattern", CloseBracketToken)
1153					return
1154				}
1155				break
1156			} else if p.tt == CloseBracketToken {
1157				array.List = array.List[:last]
1158				break
1159			}
1160
1161			array.List = append(array.List, p.parseBindingElement(decl))
1162			last = len(array.List)
1163
1164			if p.tt != CommaToken && p.tt != CloseBracketToken {
1165				p.fail("array binding pattern", CommaToken, CloseBracketToken)
1166				return
1167			}
1168		}
1169		p.next() // always CloseBracketToken
1170		binding = &array
1171	} else if p.tt == OpenBraceToken {
1172		p.next()
1173		object := BindingObject{}
1174		for p.tt != CloseBraceToken {
1175			// binding rest property
1176			if p.tt == EllipsisToken {
1177				p.next()
1178				if !p.isIdentifierReference(p.tt) {
1179					p.fail("object binding pattern", IdentifierToken)
1180					return
1181				}
1182				var ok bool
1183				object.Rest, ok = p.scope.Declare(decl, p.data)
1184				if !ok {
1185					p.failMessage("identifier %s has already been declared", string(p.data))
1186					return
1187				}
1188				p.next()
1189				if p.tt != CloseBraceToken {
1190					p.fail("object binding pattern", CloseBraceToken)
1191					return
1192				}
1193				break
1194			}
1195
1196			item := BindingObjectItem{}
1197			if p.isIdentifierReference(p.tt) {
1198				name := p.data
1199				item.Key = &PropertyName{LiteralExpr{IdentifierToken, p.data}, nil}
1200				p.next()
1201				if p.tt == ColonToken {
1202					// property name + : + binding element
1203					p.next()
1204					item.Value = p.parseBindingElement(decl)
1205				} else {
1206					// single name binding
1207					var ok bool
1208					item.Key.Literal.Data = parse.Copy(item.Key.Literal.Data) // copy so that renaming doesn't rename the key
1209					item.Value.Binding, ok = p.scope.Declare(decl, name)
1210					if !ok {
1211						p.failMessage("identifier %s has already been declared", string(name))
1212						return
1213					}
1214					if p.tt == EqToken {
1215						p.next()
1216						item.Value.Default = p.parseExpression(OpAssign)
1217					}
1218				}
1219			} else {
1220				propertyName := p.parsePropertyName("object binding pattern")
1221				item.Key = &propertyName
1222				if !p.consume("object binding pattern", ColonToken) {
1223					return
1224				}
1225				item.Value = p.parseBindingElement(decl)
1226			}
1227			object.List = append(object.List, item)
1228
1229			if p.tt == CommaToken {
1230				p.next()
1231			} else if p.tt != CloseBraceToken {
1232				p.fail("object binding pattern", CommaToken, CloseBraceToken)
1233				return
1234			}
1235		}
1236		p.next() // always CloseBracketToken
1237		binding = &object
1238	} else {
1239		p.fail("binding")
1240		return
1241	}
1242	return
1243}
1244
1245func (p *Parser) parseArrayLiteral() (array ArrayExpr) {
1246	// assume we're on [
1247	p.next()
1248	prevComma := true
1249	for {
1250		if p.tt == ErrorToken {
1251			p.fail("expression")
1252			return
1253		} else if p.tt == CloseBracketToken {
1254			p.next()
1255			break
1256		} else if p.tt == CommaToken {
1257			if prevComma {
1258				array.List = append(array.List, Element{})
1259			}
1260			prevComma = true
1261			p.next()
1262		} else {
1263			spread := p.tt == EllipsisToken
1264			if spread {
1265				p.next()
1266			}
1267			array.List = append(array.List, Element{p.parseAssignmentExpression(), spread})
1268			prevComma = false
1269			if spread && p.tt != CloseBracketToken {
1270				p.assumeArrowFunc = false
1271			}
1272		}
1273	}
1274	return
1275}
1276
1277func (p *Parser) parseObjectLiteral() (object ObjectExpr) {
1278	// assume we're on {
1279	p.next()
1280	for {
1281		if p.tt == ErrorToken {
1282			p.fail("object literal", CloseBraceToken)
1283			return
1284		} else if p.tt == CloseBraceToken {
1285			p.next()
1286			break
1287		}
1288
1289		property := Property{}
1290		if p.tt == EllipsisToken {
1291			p.next()
1292			property.Spread = true
1293			property.Value = p.parseAssignmentExpression()
1294			if _, isIdent := property.Value.(*Var); !isIdent || p.tt != CloseBraceToken {
1295				p.assumeArrowFunc = false
1296			}
1297		} else {
1298			// try to parse as MethodDefinition, otherwise fall back to PropertyName:AssignExpr or IdentifierReference
1299			var data []byte
1300			method := MethodDecl{}
1301			if p.tt == MulToken {
1302				p.next()
1303				method.Generator = true
1304			} else if p.tt == AsyncToken {
1305				data = p.data
1306				p.next()
1307				if !p.prevLT {
1308					method.Async = true
1309					if p.tt == MulToken {
1310						p.next()
1311						method.Generator = true
1312						data = nil
1313					}
1314				} else {
1315					method.Name.Literal = LiteralExpr{IdentifierToken, data}
1316					data = nil
1317				}
1318			} else if p.tt == GetToken {
1319				data = p.data
1320				p.next()
1321				method.Get = true
1322			} else if p.tt == SetToken {
1323				data = p.data
1324				p.next()
1325				method.Set = true
1326			}
1327
1328			// PropertyName
1329			if data != nil && !method.Generator && (p.tt == EqToken || p.tt == CommaToken || p.tt == CloseBraceToken || p.tt == ColonToken || p.tt == OpenParenToken) {
1330				method.Name.Literal = LiteralExpr{IdentifierToken, data}
1331				method.Async = false
1332				method.Get = false
1333				method.Set = false
1334			} else if !method.Name.IsSet() { // did not parse async [LT]
1335				method.Name = p.parsePropertyName("object literal")
1336				if !method.Name.IsSet() {
1337					return
1338				}
1339			}
1340
1341			if p.tt == OpenParenToken {
1342				// MethodDefinition
1343				parent := p.enterScope(&method.Body.Scope, true)
1344				parentAwait, parentYield := p.await, p.yield
1345				p.await, p.yield = method.Async, method.Generator
1346
1347				method.Params = p.parseFuncParams("method definition")
1348				method.Body.List = p.parseStmtList("method definition")
1349
1350				p.await, p.yield = parentAwait, parentYield
1351				p.exitScope(parent)
1352				property.Value = &method
1353				p.assumeArrowFunc = false
1354			} else if p.tt == ColonToken {
1355				// PropertyName : AssignmentExpression
1356				p.next()
1357				property.Name = &method.Name
1358				property.Value = p.parseAssignmentExpression()
1359			} else if method.Name.IsComputed() || !p.isIdentifierReference(method.Name.Literal.TokenType) {
1360				p.fail("object literal", ColonToken, OpenParenToken)
1361				return
1362			} else {
1363				// IdentifierReference (= AssignmentExpression)?
1364				name := method.Name.Literal.Data
1365				method.Name.Literal.Data = parse.Copy(method.Name.Literal.Data) // copy so that renaming doesn't rename the key
1366				property.Name = &method.Name                                    // set key explicitly so after renaming the original is still known
1367				if p.assumeArrowFunc {
1368					var ok bool
1369					property.Value, ok = p.scope.Declare(ArgumentDecl, name)
1370					if !ok {
1371						property.Value = p.scope.Use(name)
1372						p.assumeArrowFunc = false
1373					}
1374				} else {
1375					property.Value = p.scope.Use(name)
1376				}
1377				if p.tt == EqToken {
1378					p.next()
1379					parentAssumeArrowFunc := p.assumeArrowFunc
1380					p.assumeArrowFunc = false
1381					property.Init = p.parseExpression(OpAssign)
1382					p.assumeArrowFunc = parentAssumeArrowFunc
1383				}
1384			}
1385		}
1386		object.List = append(object.List, property)
1387		if p.tt == CommaToken {
1388			p.next()
1389		} else if p.tt != CloseBraceToken {
1390			p.fail("object literal")
1391			return
1392		}
1393	}
1394	return
1395}
1396
1397func (p *Parser) parseTemplateLiteral(precLeft OpPrec) (template TemplateExpr) {
1398	// assume we're on 'Template' or 'TemplateStart'
1399	template.Prec = OpMember
1400	if precLeft < OpMember {
1401		template.Prec = OpCall
1402	}
1403	for p.tt == TemplateStartToken || p.tt == TemplateMiddleToken {
1404		tpl := p.data
1405		p.next()
1406		template.List = append(template.List, TemplatePart{tpl, p.parseExpression(OpExpr)})
1407	}
1408	if p.tt != TemplateToken && p.tt != TemplateEndToken {
1409		p.fail("template literal", TemplateToken)
1410		return
1411	}
1412	template.Tail = p.data
1413	p.next() // TemplateEndToken
1414	return
1415}
1416
1417func (p *Parser) parseArguments() (args Args) {
1418	// assume we're on (
1419	p.next()
1420	args.List = make([]Arg, 0, 4)
1421	for {
1422		rest := p.tt == EllipsisToken
1423		if rest {
1424			p.next()
1425		}
1426
1427		if p.tt == CloseParenToken || p.tt == ErrorToken {
1428			break
1429		}
1430		args.List = append(args.List, Arg{
1431			Value: p.parseExpression(OpAssign),
1432			Rest:  rest,
1433		})
1434		if p.tt == CommaToken {
1435			p.next()
1436		}
1437	}
1438	p.consume("arguments", CloseParenToken)
1439	return
1440}
1441
1442func (p *Parser) parseAsyncArrowFunc() (arrowFunc *ArrowFunc) {
1443	// expect we're at Identifier or Yield or (
1444	arrowFunc = &ArrowFunc{}
1445	parent := p.enterScope(&arrowFunc.Body.Scope, true)
1446	parentAwait, parentYield := p.await, p.yield
1447	p.await, p.yield = true, false
1448
1449	if IsIdentifier(p.tt) || !p.yield && p.tt == YieldToken {
1450		ref, _ := p.scope.Declare(ArgumentDecl, p.data) // cannot fail
1451		p.next()
1452		arrowFunc.Params.List = []BindingElement{{Binding: ref}}
1453	} else {
1454		arrowFunc.Params = p.parseFuncParams("arrow function")
1455
1456		// could be CallExpression of: async(params)
1457		if p.tt != ArrowToken {
1458			// TODO?
1459		}
1460	}
1461
1462	p.await, p.yield = true, parentYield
1463	arrowFunc.Async = true
1464	arrowFunc.Body.List = p.parseArrowFuncBody()
1465
1466	p.await, p.yield = parentAwait, parentYield
1467	p.exitScope(parent)
1468	return
1469}
1470
1471func (p *Parser) parseIdentifierArrowFunc(v *Var) (arrowFunc *ArrowFunc) {
1472	// expect we're at =>
1473	arrowFunc = &ArrowFunc{}
1474	parent := p.enterScope(&arrowFunc.Body.Scope, true)
1475	parentAwait, parentYield := p.await, p.yield
1476
1477	if 1 < v.Uses {
1478		v.Uses--
1479		v, _ = p.scope.Declare(ArgumentDecl, parse.Copy(v.Data)) // cannot fail
1480	} else {
1481		// if v.Uses==1 it must be undeclared and be the last added
1482		p.scope.Parent.Undeclared = p.scope.Parent.Undeclared[:len(p.scope.Parent.Undeclared)-1]
1483		v.Decl = ArgumentDecl
1484		p.scope.Declared = append(p.scope.Declared, v)
1485	}
1486
1487	p.await = false
1488	arrowFunc.Params.List = []BindingElement{{v, nil}}
1489	arrowFunc.Body.List = p.parseArrowFuncBody()
1490
1491	p.await, p.yield = parentAwait, parentYield
1492	p.exitScope(parent)
1493	return
1494}
1495
1496func (p *Parser) parseArrowFuncBody() (list []IStmt) {
1497	// expect we're at arrow
1498	if p.tt != ArrowToken {
1499		p.fail("arrow function", ArrowToken)
1500		return
1501	} else if p.prevLT {
1502		p.fail("expression")
1503		return
1504	}
1505	p.next()
1506
1507	// mark undeclared vars as arguments in `function f(a=b){var b}` where the b's are different vars
1508	p.scope.MarkFuncArgs()
1509
1510	if p.tt == OpenBraceToken {
1511		parentInFor := p.inFor
1512		p.inFor = false
1513		p.yield = false
1514		p.allowDirectivePrologue = true
1515		list = p.parseStmtList("arrow function")
1516		p.inFor = parentInFor
1517	} else {
1518		list = []IStmt{&ReturnStmt{p.parseExpression(OpAssign)}}
1519	}
1520	return
1521}
1522
1523func (p *Parser) parseIdentifierExpression(prec OpPrec, ident []byte) IExpr {
1524	var left IExpr
1525	left = p.scope.Use(ident)
1526	return p.parseExpressionSuffix(left, prec, OpPrimary)
1527}
1528
1529func (p *Parser) parseAsyncExpression(prec OpPrec, async []byte) IExpr {
1530	// assume we're at a token after async
1531	var left IExpr
1532	precLeft := OpPrimary
1533	if !p.prevLT && p.tt == FunctionToken {
1534		// primary expression
1535		left = p.parseAsyncFuncExpr()
1536	} else if !p.prevLT && prec <= OpAssign && (p.tt == OpenParenToken || IsIdentifier(p.tt) || !p.yield && p.tt == YieldToken || p.tt == AwaitToken) {
1537		// async arrow function expression
1538		if p.tt == AwaitToken {
1539			p.fail("arrow function")
1540			return nil
1541		} else if p.tt == OpenParenToken {
1542			return p.parseParenthesizedExpressionOrArrowFunc(prec, async)
1543		}
1544		left = p.parseAsyncArrowFunc()
1545		precLeft = OpAssign
1546	} else {
1547		left = p.scope.Use(async)
1548	}
1549	return p.parseExpressionSuffix(left, prec, precLeft)
1550}
1551
1552// parseExpression parses an expression that has a precedence of prec or higher.
1553func (p *Parser) parseExpression(prec OpPrec) IExpr {
1554	p.exprLevel++
1555	if 1000 < p.exprLevel {
1556		p.failMessage("too many nested expressions")
1557		return nil
1558	}
1559
1560	// reparse input if we have / or /= as the beginning of a new expression, this should be a regular expression!
1561	if p.tt == DivToken || p.tt == DivEqToken {
1562		p.tt, p.data = p.l.RegExp()
1563		if p.tt == ErrorToken {
1564			p.fail("regular expression")
1565			return nil
1566		}
1567	}
1568
1569	var left IExpr
1570	precLeft := OpPrimary
1571
1572	if IsIdentifier(p.tt) && p.tt != AsyncToken {
1573		left = p.scope.Use(p.data)
1574		p.next()
1575		suffix := p.parseExpressionSuffix(left, prec, precLeft)
1576		p.exprLevel--
1577		return suffix
1578	} else if IsNumeric(p.tt) {
1579		left = &LiteralExpr{p.tt, p.data}
1580		p.next()
1581		suffix := p.parseExpressionSuffix(left, prec, precLeft)
1582		p.exprLevel--
1583		return suffix
1584	}
1585
1586	switch tt := p.tt; tt {
1587	case StringToken, ThisToken, NullToken, TrueToken, FalseToken, RegExpToken:
1588		left = &LiteralExpr{p.tt, p.data}
1589		p.next()
1590	case OpenBracketToken:
1591		parentInFor := p.inFor
1592		p.inFor = false
1593		array := p.parseArrayLiteral()
1594		left = &array
1595		p.inFor = parentInFor
1596	case OpenBraceToken:
1597		parentInFor := p.inFor
1598		p.inFor = false
1599		object := p.parseObjectLiteral()
1600		left = &object
1601		p.inFor = parentInFor
1602	case OpenParenToken:
1603		// parenthesized expression or arrow parameter list
1604		if OpAssign < prec {
1605			// must be a parenthesized expression
1606			p.next()
1607			parentInFor := p.inFor
1608			p.inFor = false
1609			left = &GroupExpr{p.parseExpression(OpExpr)}
1610			p.inFor = parentInFor
1611			if !p.consume("expression", CloseParenToken) {
1612				return nil
1613			}
1614			break
1615		}
1616		suffix := p.parseParenthesizedExpressionOrArrowFunc(prec, nil)
1617		p.exprLevel--
1618		return suffix
1619	case NotToken, BitNotToken, TypeofToken, VoidToken, DeleteToken:
1620		if OpUnary < prec {
1621			p.fail("expression")
1622			return nil
1623		}
1624		p.next()
1625		left = &UnaryExpr{tt, p.parseExpression(OpUnary)}
1626		precLeft = OpUnary
1627	case AddToken:
1628		if OpUnary < prec {
1629			p.fail("expression")
1630			return nil
1631		}
1632		p.next()
1633		left = &UnaryExpr{PosToken, p.parseExpression(OpUnary)}
1634		precLeft = OpUnary
1635	case SubToken:
1636		if OpUnary < prec {
1637			p.fail("expression")
1638			return nil
1639		}
1640		p.next()
1641		left = &UnaryExpr{NegToken, p.parseExpression(OpUnary)}
1642		precLeft = OpUnary
1643	case IncrToken:
1644		if OpUpdate < prec {
1645			p.fail("expression")
1646			return nil
1647		}
1648		p.next()
1649		left = &UnaryExpr{PreIncrToken, p.parseExpression(OpUnary)}
1650		precLeft = OpUnary
1651	case DecrToken:
1652		if OpUpdate < prec {
1653			p.fail("expression")
1654			return nil
1655		}
1656		p.next()
1657		left = &UnaryExpr{PreDecrToken, p.parseExpression(OpUnary)}
1658		precLeft = OpUnary
1659	case AwaitToken:
1660		// either accepted as IdentifierReference or as AwaitExpression
1661		if p.await && prec <= OpUnary {
1662			p.next()
1663			left = &UnaryExpr{tt, p.parseExpression(OpUnary)}
1664			precLeft = OpUnary
1665		} else if p.await {
1666			p.fail("expression")
1667			return nil
1668		} else {
1669			left = p.scope.Use(p.data)
1670			p.next()
1671		}
1672	case NewToken:
1673		p.next()
1674		if p.tt == DotToken {
1675			p.next()
1676			if !p.consume("new.target expression", TargetToken) {
1677				return nil
1678			}
1679			left = &NewTargetExpr{}
1680			precLeft = OpMember
1681		} else {
1682			newExpr := &NewExpr{p.parseExpression(OpNew), nil}
1683			if p.tt == OpenParenToken {
1684				args := p.parseArguments()
1685				if len(args.List) != 0 {
1686					newExpr.Args = &args
1687				}
1688				precLeft = OpMember
1689			} else {
1690				precLeft = OpNew
1691			}
1692			left = newExpr
1693		}
1694	case ImportToken:
1695		// OpMember < prec does never happen
1696		left = &LiteralExpr{p.tt, p.data}
1697		p.next()
1698		if p.tt == DotToken {
1699			p.next()
1700			if !p.consume("import.meta expression", MetaToken) {
1701				return nil
1702			}
1703			left = &ImportMetaExpr{}
1704			precLeft = OpMember
1705		} else if p.tt != OpenParenToken {
1706			p.fail("import expression", OpenParenToken)
1707			return nil
1708		} else if OpCall < prec {
1709			p.fail("expression")
1710			return nil
1711		} else {
1712			precLeft = OpCall
1713		}
1714	case SuperToken:
1715		// OpMember < prec does never happen
1716		left = &LiteralExpr{p.tt, p.data}
1717		p.next()
1718		if OpCall < prec && p.tt != DotToken && p.tt != OpenBracketToken {
1719			p.fail("super expression", OpenBracketToken, DotToken)
1720			return nil
1721		} else if p.tt != DotToken && p.tt != OpenBracketToken && p.tt != OpenParenToken {
1722			p.fail("super expression", OpenBracketToken, OpenParenToken, DotToken)
1723			return nil
1724		}
1725		if OpCall < prec {
1726			precLeft = OpMember
1727		} else {
1728			precLeft = OpCall
1729		}
1730	case YieldToken:
1731		// either accepted as IdentifierReference or as YieldExpression
1732		if p.yield && prec <= OpAssign {
1733			// YieldExpression
1734			p.next()
1735			yieldExpr := YieldExpr{}
1736			if !p.prevLT {
1737				yieldExpr.Generator = p.tt == MulToken
1738				if yieldExpr.Generator {
1739					p.next()
1740					yieldExpr.X = p.parseExpression(OpAssign)
1741				} else if p.tt != CloseBraceToken && p.tt != CloseBracketToken && p.tt != CloseParenToken && p.tt != ColonToken && p.tt != CommaToken && p.tt != SemicolonToken {
1742					yieldExpr.X = p.parseExpression(OpAssign)
1743				}
1744			}
1745			left = &yieldExpr
1746			precLeft = OpAssign
1747		} else if p.yield {
1748			p.fail("expression")
1749			return nil
1750		} else {
1751			left = p.scope.Use(p.data)
1752			p.next()
1753		}
1754	case AsyncToken:
1755		async := p.data
1756		p.next()
1757		left = p.parseAsyncExpression(prec, async)
1758	case ClassToken:
1759		parentInFor := p.inFor
1760		p.inFor = false
1761		left = p.parseClassExpr()
1762		p.inFor = parentInFor
1763	case FunctionToken:
1764		parentInFor := p.inFor
1765		p.inFor = false
1766		left = p.parseFuncExpr()
1767		p.inFor = parentInFor
1768	case TemplateToken, TemplateStartToken:
1769		parentInFor := p.inFor
1770		p.inFor = false
1771		template := p.parseTemplateLiteral(precLeft)
1772		left = &template
1773		p.inFor = parentInFor
1774	default:
1775		p.fail("expression")
1776		return nil
1777	}
1778	suffix := p.parseExpressionSuffix(left, prec, precLeft)
1779	p.exprLevel--
1780	return suffix
1781}
1782
1783func (p *Parser) parseExpressionSuffix(left IExpr, prec, precLeft OpPrec) IExpr {
1784	for i := 0; ; i++ {
1785		if 1000 < p.exprLevel+i {
1786			p.failMessage("too many nested expressions")
1787			return nil
1788		}
1789
1790		switch tt := p.tt; tt {
1791		case EqToken, MulEqToken, DivEqToken, ModEqToken, ExpEqToken, AddEqToken, SubEqToken, LtLtEqToken, GtGtEqToken, GtGtGtEqToken, BitAndEqToken, BitXorEqToken, BitOrEqToken, AndEqToken, OrEqToken, NullishEqToken:
1792			if OpAssign < prec {
1793				return left
1794			} else if precLeft < OpLHS {
1795				p.fail("expression")
1796				return nil
1797			}
1798			p.next()
1799			left = &BinaryExpr{tt, left, p.parseExpression(OpAssign)}
1800			precLeft = OpAssign
1801		case LtToken, LtEqToken, GtToken, GtEqToken, InToken, InstanceofToken:
1802			if OpCompare < prec || p.inFor && tt == InToken {
1803				return left
1804			} else if precLeft < OpCompare {
1805				// can only fail after a yield or arrow function expression
1806				p.fail("expression")
1807				return nil
1808			}
1809			p.next()
1810			left = &BinaryExpr{tt, left, p.parseExpression(OpShift)}
1811			precLeft = OpCompare
1812		case EqEqToken, NotEqToken, EqEqEqToken, NotEqEqToken:
1813			if OpEquals < prec {
1814				return left
1815			} else if precLeft < OpEquals {
1816				// can only fail after a yield or arrow function expression
1817				p.fail("expression")
1818				return nil
1819			}
1820			p.next()
1821			left = &BinaryExpr{tt, left, p.parseExpression(OpCompare)}
1822			precLeft = OpEquals
1823		case AndToken:
1824			if OpAnd < prec {
1825				return left
1826			} else if precLeft < OpAnd {
1827				p.fail("expression")
1828				return nil
1829			}
1830			p.next()
1831			left = &BinaryExpr{tt, left, p.parseExpression(OpBitOr)}
1832			precLeft = OpAnd
1833		case OrToken:
1834			if OpOr < prec {
1835				return left
1836			} else if precLeft < OpOr {
1837				p.fail("expression")
1838				return nil
1839			}
1840			p.next()
1841			left = &BinaryExpr{tt, left, p.parseExpression(OpAnd)}
1842			precLeft = OpOr
1843		case NullishToken:
1844			if OpCoalesce < prec {
1845				return left
1846			} else if precLeft < OpBitOr && precLeft != OpCoalesce {
1847				p.fail("expression")
1848				return nil
1849			}
1850			p.next()
1851			left = &BinaryExpr{tt, left, p.parseExpression(OpBitOr)}
1852			precLeft = OpCoalesce
1853		case DotToken:
1854			// OpMember < prec does never happen
1855			if precLeft < OpCall {
1856				p.fail("expression")
1857				return nil
1858			}
1859			p.next()
1860			if !IsIdentifierName(p.tt) && p.tt != PrivateIdentifierToken {
1861				p.fail("dot expression", IdentifierToken)
1862				return nil
1863			}
1864			exprPrec := OpMember
1865			if precLeft < OpMember {
1866				exprPrec = OpCall
1867			}
1868			if p.tt != PrivateIdentifierToken {
1869				p.tt = IdentifierToken
1870			}
1871			left = &DotExpr{left, LiteralExpr{p.tt, p.data}, exprPrec, false}
1872			p.next()
1873			if precLeft < OpMember {
1874				precLeft = OpCall
1875			} else {
1876				precLeft = OpMember
1877			}
1878		case OpenBracketToken:
1879			// OpMember < prec does never happen
1880			if precLeft < OpCall {
1881				p.fail("expression")
1882				return nil
1883			}
1884			p.next()
1885			exprPrec := OpMember
1886			if precLeft < OpMember {
1887				exprPrec = OpCall
1888			}
1889			parentInFor := p.inFor
1890			p.inFor = false
1891			left = &IndexExpr{left, p.parseExpression(OpExpr), exprPrec, false}
1892			p.inFor = parentInFor
1893			if !p.consume("index expression", CloseBracketToken) {
1894				return nil
1895			}
1896			if precLeft < OpMember {
1897				precLeft = OpCall
1898			} else {
1899				precLeft = OpMember
1900			}
1901		case OpenParenToken:
1902			if OpCall < prec {
1903				return left
1904			} else if precLeft < OpCall {
1905				p.fail("expression")
1906				return nil
1907			}
1908			parentInFor := p.inFor
1909			p.inFor = false
1910			left = &CallExpr{left, p.parseArguments(), false}
1911			precLeft = OpCall
1912			p.inFor = parentInFor
1913		case TemplateToken, TemplateStartToken:
1914			// OpMember < prec does never happen
1915			if precLeft < OpCall {
1916				p.fail("expression")
1917				return nil
1918			}
1919			parentInFor := p.inFor
1920			p.inFor = false
1921			template := p.parseTemplateLiteral(precLeft)
1922			template.Tag = left
1923			left = &template
1924			if precLeft < OpMember {
1925				precLeft = OpCall
1926			} else {
1927				precLeft = OpMember
1928			}
1929			p.inFor = parentInFor
1930		case OptChainToken:
1931			if OpCall < prec {
1932				return left
1933			}
1934			p.next()
1935			if p.tt == OpenParenToken {
1936				left = &CallExpr{left, p.parseArguments(), true}
1937			} else if p.tt == OpenBracketToken {
1938				p.next()
1939				left = &IndexExpr{left, p.parseExpression(OpExpr), OpCall, true}
1940				if !p.consume("optional chaining expression", CloseBracketToken) {
1941					return nil
1942				}
1943			} else if p.tt == TemplateToken || p.tt == TemplateStartToken {
1944				template := p.parseTemplateLiteral(precLeft)
1945				template.Prec = OpCall
1946				template.Tag = left
1947				template.Optional = true
1948				left = &template
1949			} else if IsIdentifierName(p.tt) {
1950				left = &DotExpr{left, LiteralExpr{IdentifierToken, p.data}, OpCall, true}
1951				p.next()
1952			} else if p.tt == PrivateIdentifierToken {
1953				left = &DotExpr{left, LiteralExpr{p.tt, p.data}, OpCall, true}
1954				p.next()
1955			} else {
1956				p.fail("optional chaining expression", IdentifierToken, OpenParenToken, OpenBracketToken, TemplateToken)
1957				return nil
1958			}
1959			precLeft = OpCall
1960		case IncrToken:
1961			if p.prevLT || OpUpdate < prec {
1962				return left
1963			} else if precLeft < OpLHS {
1964				p.fail("expression")
1965				return nil
1966			}
1967			p.next()
1968			left = &UnaryExpr{PostIncrToken, left}
1969			precLeft = OpUpdate
1970		case DecrToken:
1971			if p.prevLT || OpUpdate < prec {
1972				return left
1973			} else if precLeft < OpLHS {
1974				p.fail("expression")
1975				return nil
1976			}
1977			p.next()
1978			left = &UnaryExpr{PostDecrToken, left}
1979			precLeft = OpUpdate
1980		case ExpToken:
1981			if OpExp < prec {
1982				return left
1983			} else if precLeft < OpUpdate {
1984				p.fail("expression")
1985				return nil
1986			}
1987			p.next()
1988			left = &BinaryExpr{tt, left, p.parseExpression(OpExp)}
1989			precLeft = OpExp
1990		case MulToken, DivToken, ModToken:
1991			if OpMul < prec {
1992				return left
1993			} else if precLeft < OpMul {
1994				p.fail("expression")
1995				return nil
1996			}
1997			p.next()
1998			left = &BinaryExpr{tt, left, p.parseExpression(OpExp)}
1999			precLeft = OpMul
2000		case AddToken, SubToken:
2001			if OpAdd < prec {
2002				return left
2003			} else if precLeft < OpAdd {
2004				p.fail("expression")
2005				return nil
2006			}
2007			p.next()
2008			left = &BinaryExpr{tt, left, p.parseExpression(OpMul)}
2009			precLeft = OpAdd
2010		case LtLtToken, GtGtToken, GtGtGtToken:
2011			if OpShift < prec {
2012				return left
2013			} else if precLeft < OpShift {
2014				p.fail("expression")
2015				return nil
2016			}
2017			p.next()
2018			left = &BinaryExpr{tt, left, p.parseExpression(OpAdd)}
2019			precLeft = OpShift
2020		case BitAndToken:
2021			if OpBitAnd < prec {
2022				return left
2023			} else if precLeft < OpBitAnd {
2024				p.fail("expression")
2025				return nil
2026			}
2027			p.next()
2028			left = &BinaryExpr{tt, left, p.parseExpression(OpEquals)}
2029			precLeft = OpBitAnd
2030		case BitXorToken:
2031			if OpBitXor < prec {
2032				return left
2033			} else if precLeft < OpBitXor {
2034				p.fail("expression")
2035				return nil
2036			}
2037			p.next()
2038			left = &BinaryExpr{tt, left, p.parseExpression(OpBitAnd)}
2039			precLeft = OpBitXor
2040		case BitOrToken:
2041			if OpBitOr < prec {
2042				return left
2043			} else if precLeft < OpBitOr {
2044				p.fail("expression")
2045				return nil
2046			}
2047			p.next()
2048			left = &BinaryExpr{tt, left, p.parseExpression(OpBitXor)}
2049			precLeft = OpBitOr
2050		case QuestionToken:
2051			if OpAssign < prec {
2052				return left
2053			} else if precLeft < OpCoalesce {
2054				p.fail("expression")
2055				return nil
2056			}
2057			p.next()
2058			ifExpr := p.parseExpression(OpAssign)
2059			if !p.consume("conditional expression", ColonToken) {
2060				return nil
2061			}
2062			elseExpr := p.parseExpression(OpAssign)
2063			left = &CondExpr{left, ifExpr, elseExpr}
2064			precLeft = OpAssign
2065		case CommaToken:
2066			if OpExpr < prec {
2067				return left
2068			}
2069			p.next()
2070			if commaExpr, ok := left.(*CommaExpr); ok {
2071				commaExpr.List = append(commaExpr.List, p.parseExpression(OpAssign))
2072				i-- // adjust expression nesting limit
2073			} else {
2074				left = &CommaExpr{[]IExpr{left, p.parseExpression(OpAssign)}}
2075			}
2076			precLeft = OpExpr
2077		case ArrowToken:
2078			// handle identifier => ..., where identifier could also be yield or await
2079			if OpAssign < prec {
2080				return left
2081			} else if precLeft < OpPrimary {
2082				p.fail("expression")
2083				return nil
2084			}
2085
2086			v, ok := left.(*Var)
2087			if !ok {
2088				p.fail("expression")
2089				return nil
2090			}
2091
2092			left = p.parseIdentifierArrowFunc(v)
2093			precLeft = OpAssign
2094		default:
2095			return left
2096		}
2097	}
2098}
2099
2100func (p *Parser) parseAssignmentExpression() IExpr {
2101	// this could be a BindingElement or an AssignmentExpression. Here we handle BindingIdentifier with a possible Initializer, BindingPattern will be handled by parseArrayLiteral or parseObjectLiteral
2102	if p.assumeArrowFunc && p.isIdentifierReference(p.tt) {
2103		tt := p.tt
2104		data := p.data
2105		p.next()
2106		if p.tt == EqToken || p.tt == CommaToken || p.tt == CloseParenToken || p.tt == CloseBraceToken || p.tt == CloseBracketToken {
2107			var ok bool
2108			var left IExpr
2109			left, ok = p.scope.Declare(ArgumentDecl, data)
2110			if ok {
2111				p.assumeArrowFunc = false
2112				left = p.parseExpressionSuffix(left, OpAssign, OpPrimary)
2113				p.assumeArrowFunc = true
2114				return left
2115			}
2116		}
2117		p.assumeArrowFunc = false
2118		if tt == AsyncToken {
2119			return p.parseAsyncExpression(OpAssign, data)
2120		}
2121		return p.parseIdentifierExpression(OpAssign, data)
2122	} else if p.tt != OpenBracketToken && p.tt != OpenBraceToken {
2123		p.assumeArrowFunc = false
2124	}
2125	return p.parseExpression(OpAssign)
2126}
2127
2128func (p *Parser) parseParenthesizedExpressionOrArrowFunc(prec OpPrec, async []byte) IExpr {
2129	var left IExpr
2130	precLeft := OpPrimary
2131
2132	// expect to be at (
2133	p.next()
2134
2135	isAsync := async != nil
2136	arrowFunc := &ArrowFunc{}
2137	parent := p.enterScope(&arrowFunc.Body.Scope, true)
2138	parentAssumeArrowFunc, parentInFor := p.assumeArrowFunc, p.inFor
2139	p.assumeArrowFunc, p.inFor = true, false
2140
2141	// parse a parenthesized expression but assume we might be parsing an (async) arrow function. If this is really an arrow function, parsing as a parenthesized expression cannot fail as AssignmentExpression, ArrayLiteral, and ObjectLiteral are supersets of SingleNameBinding, ArrayBindingPattern, and ObjectBindingPattern respectively. Any identifier that would be a BindingIdentifier in case of an arrow function, will be added as such. If finally this is not an arrow function, we will demote those variables an undeclared and merge them with the parent scope.
2142
2143	var list []IExpr
2144	var rest IExpr
2145	for p.tt != CloseParenToken && p.tt != ErrorToken {
2146		if p.tt == EllipsisToken && p.assumeArrowFunc {
2147			p.next()
2148			if isAsync {
2149				rest = p.parseAssignmentExpression()
2150				if p.tt == CommaToken {
2151					p.next()
2152				}
2153			} else if p.isIdentifierReference(p.tt) {
2154				var ok bool
2155				rest, ok = p.scope.Declare(ArgumentDecl, p.data)
2156				if !ok {
2157					p.failMessage("identifier %s has already been declared", string(p.data))
2158					return nil
2159				}
2160				p.next()
2161			} else if p.tt == OpenBracketToken {
2162				array := p.parseArrayLiteral()
2163				rest = &array
2164			} else if p.tt == OpenBraceToken {
2165				object := p.parseObjectLiteral()
2166				rest = &object
2167			} else {
2168				p.fail("arrow function")
2169				return nil
2170			}
2171			break
2172		}
2173
2174		list = append(list, p.parseAssignmentExpression())
2175		if p.tt != CommaToken {
2176			break
2177		}
2178		p.next()
2179	}
2180	if p.tt != CloseParenToken {
2181		p.fail("expression")
2182		return nil
2183	}
2184	p.next()
2185	isArrowFunc := p.tt == ArrowToken && p.assumeArrowFunc
2186	p.assumeArrowFunc, p.inFor = parentAssumeArrowFunc, parentInFor
2187
2188	if isArrowFunc {
2189		parentAwait, parentYield := p.await, p.yield
2190		p.await = isAsync
2191
2192		// arrow function
2193		arrowFunc.Params = Params{List: make([]BindingElement, len(list))}
2194		for i, item := range list {
2195			arrowFunc.Params.List[i] = p.exprToBindingElement(item) // can not fail when assumArrowFunc is set
2196		}
2197		arrowFunc.Async = isAsync
2198		arrowFunc.Params.Rest = p.exprToBinding(rest)
2199		arrowFunc.Body.List = p.parseArrowFuncBody()
2200
2201		p.await, p.yield = parentAwait, parentYield
2202		p.exitScope(parent)
2203
2204		left = arrowFunc
2205		precLeft = OpAssign
2206	} else if len(list) == 0 || !isAsync && rest != nil || isAsync && OpCall < prec {
2207		p.fail("arrow function", ArrowToken)
2208		return nil
2209	} else {
2210		p.exitScope(parent)
2211
2212		// for any nested FuncExpr/ArrowFunc scope, Parent will point to the temporary scope created in case this was an arrow function instead of a parenthesized expression. This is not a problem as Parent is only used for defining new variables, and we already parsed all the nested scopes so that Parent (not Func) are not relevant anymore. Anyways, the Parent will just point to an empty scope, whose Parent/Func will point to valid scopes. This should not be a big deal.
2213		// Here we move all declared ArgumentDecls (in case of an arrow function) to its parent scope as undeclared variables (identifiers used in a parenthesized expression).
2214		arrowFunc.Body.Scope.UndeclareScope()
2215
2216		if isAsync {
2217			// call expression
2218			args := Args{}
2219			for _, item := range list {
2220				args.List = append(args.List, Arg{Value: item, Rest: false})
2221			}
2222			if rest != nil {
2223				args.List = append(args.List, Arg{Value: rest, Rest: true})
2224			}
2225			left = p.scope.Use(async)
2226			left = &CallExpr{left, args, false}
2227			precLeft = OpCall
2228		} else {
2229			// parenthesized expression
2230			if 1 < len(list) {
2231				left = &GroupExpr{&CommaExpr{list}}
2232			} else {
2233				left = &GroupExpr{list[0]}
2234			}
2235		}
2236	}
2237	return p.parseExpressionSuffix(left, prec, precLeft)
2238}
2239
2240// exprToBinding converts a CoverParenthesizedExpressionAndArrowParameterList into FormalParameters
2241// Any unbound variables of the parameters (Initializer, ComputedPropertyName) are kept in the parent scope
2242func (p *Parser) exprToBinding(expr IExpr) (binding IBinding) {
2243	if v, ok := expr.(*Var); ok {
2244		binding = v
2245	} else if array, ok := expr.(*ArrayExpr); ok {
2246		bindingArray := BindingArray{}
2247		for _, item := range array.List {
2248			if item.Spread {
2249				// can only BindingIdentifier or BindingPattern
2250				bindingArray.Rest = p.exprToBinding(item.Value)
2251				break
2252			}
2253			var bindingElement BindingElement
2254			bindingElement = p.exprToBindingElement(item.Value)
2255			bindingArray.List = append(bindingArray.List, bindingElement)
2256		}
2257		binding = &bindingArray
2258	} else if object, ok := expr.(*ObjectExpr); ok {
2259		bindingObject := BindingObject{}
2260		for _, item := range object.List {
2261			if item.Spread {
2262				// can only be BindingIdentifier
2263				bindingObject.Rest = item.Value.(*Var)
2264				break
2265			}
2266			var bindingElement BindingElement
2267			bindingElement.Binding = p.exprToBinding(item.Value)
2268			if bindingElement.Binding == nil {
2269				bindingElement = p.exprToBindingElement(item.Value)
2270			} else if item.Init != nil {
2271				bindingElement.Default = item.Init
2272			}
2273			bindingObject.List = append(bindingObject.List, BindingObjectItem{Key: item.Name, Value: bindingElement})
2274		}
2275		binding = &bindingObject
2276	}
2277	return
2278}
2279
2280func (p *Parser) exprToBindingElement(expr IExpr) (bindingElement BindingElement) {
2281	if assign, ok := expr.(*BinaryExpr); ok && assign.Op == EqToken {
2282		bindingElement.Binding = p.exprToBinding(assign.X)
2283		bindingElement.Default = assign.Y
2284	} else {
2285		bindingElement.Binding = p.exprToBinding(expr)
2286	}
2287	return
2288}
2289
2290func (p *Parser) isIdentifierReference(tt TokenType) bool {
2291	return IsIdentifier(tt) || tt == YieldToken && !p.yield || tt == AwaitToken && !p.await
2292}