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}