1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
import {types as tt} from "./tokentype"
import {Parser} from "./state"
import {lineBreak, skipWhiteSpace} from "./whitespace"
const pp = Parser.prototype
// ## Parser utilities
const literal = /^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/
pp.strictDirective = function(start) {
for (;;) {
skipWhiteSpace.lastIndex = start
start += skipWhiteSpace.exec(this.input)[0].length
let match = literal.exec(this.input.slice(start))
if (!match) return false
if ((match[1] || match[2]) == "use strict") return true
start += match[0].length
}
}
// Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.
pp.eat = function(type) {
if (this.type === type) {
this.next()
return true
} else {
return false
}
}
// Tests whether parsed token is a contextual keyword.
pp.isContextual = function(name) {
return this.type === tt.name && this.value === name
}
// Consumes contextual keyword if possible.
pp.eatContextual = function(name) {
return this.value === name && this.eat(tt.name)
}
// Asserts that following token is given contextual keyword.
pp.expectContextual = function(name) {
if (!this.eatContextual(name)) this.unexpected()
}
// Test whether a semicolon can be inserted at the current position.
pp.canInsertSemicolon = function() {
return this.type === tt.eof ||
this.type === tt.braceR ||
lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
}
pp.insertSemicolon = function() {
if (this.canInsertSemicolon()) {
if (this.options.onInsertedSemicolon)
this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc)
return true
}
}
// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.
pp.semicolon = function() {
if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected()
}
pp.afterTrailingComma = function(tokType, notNext) {
if (this.type == tokType) {
if (this.options.onTrailingComma)
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc)
if (!notNext)
this.next()
return true
}
}
// Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.
pp.expect = function(type) {
this.eat(type) || this.unexpected()
}
// Raise an unexpected token error.
pp.unexpected = function(pos) {
this.raise(pos != null ? pos : this.start, "Unexpected token")
}
export class DestructuringErrors {
constructor() {
this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1
}
}
pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
if (!refDestructuringErrors) return
if (refDestructuringErrors.trailingComma > -1)
this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element")
let parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind
if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern")
}
pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
let pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1
if (!andThrow) return pos >= 0
if (pos > -1) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns")
}
pp.checkYieldAwaitInDefaultParams = function() {
if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
this.raise(this.yieldPos, "Yield expression cannot be a default value")
if (this.awaitPos)
this.raise(this.awaitPos, "Await expression cannot be a default value")
}
pp.isSimpleAssignTarget = function(expr) {
if (expr.type === "ParenthesizedExpression")
return this.isSimpleAssignTarget(expr.expression)
return expr.type === "Identifier" || expr.type === "MemberExpression"
}
|