UNPKG

5.27 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.ExpressionErrors = exports.default = void 0;
7
8var _types = require("../tokenizer/types");
9
10var _tokenizer = _interopRequireDefault(require("../tokenizer"));
11
12var _state = _interopRequireDefault(require("../tokenizer/state"));
13
14var _whitespace = require("../util/whitespace");
15
16var _identifier = require("../util/identifier");
17
18var _error = require("./error");
19
20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22class UtilParser extends _tokenizer.default {
23 addExtra(node, key, val) {
24 if (!node) return;
25 const extra = node.extra = node.extra || {};
26 extra[key] = val;
27 }
28
29 isRelational(op) {
30 return this.match(_types.types.relational) && this.state.value === op;
31 }
32
33 expectRelational(op) {
34 if (this.isRelational(op)) {
35 this.next();
36 } else {
37 this.unexpected(null, _types.types.relational);
38 }
39 }
40
41 isContextual(name) {
42 return this.match(_types.types.name) && this.state.value === name && !this.state.containsEsc;
43 }
44
45 isUnparsedContextual(nameStart, name) {
46 const nameEnd = nameStart + name.length;
47 return this.input.slice(nameStart, nameEnd) === name && (nameEnd === this.input.length || !(0, _identifier.isIdentifierChar)(this.input.charCodeAt(nameEnd)));
48 }
49
50 isLookaheadContextual(name) {
51 const next = this.nextTokenStart();
52 return this.isUnparsedContextual(next, name);
53 }
54
55 eatContextual(name) {
56 return this.isContextual(name) && this.eat(_types.types.name);
57 }
58
59 expectContextual(name, message) {
60 if (!this.eatContextual(name)) this.unexpected(null, message);
61 }
62
63 canInsertSemicolon() {
64 return this.match(_types.types.eof) || this.match(_types.types.braceR) || this.hasPrecedingLineBreak();
65 }
66
67 hasPrecedingLineBreak() {
68 return _whitespace.lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start));
69 }
70
71 isLineTerminator() {
72 return this.eat(_types.types.semi) || this.canInsertSemicolon();
73 }
74
75 semicolon() {
76 if (!this.isLineTerminator()) this.unexpected(null, _types.types.semi);
77 }
78
79 expect(type, pos) {
80 this.eat(type) || this.unexpected(pos, type);
81 }
82
83 assertNoSpace(message = "Unexpected space.") {
84 if (this.state.start > this.state.lastTokEnd) {
85 this.raise(this.state.lastTokEnd, message);
86 }
87 }
88
89 unexpected(pos, messageOrType = "Unexpected token") {
90 if (typeof messageOrType !== "string") {
91 messageOrType = `Unexpected token, expected "${messageOrType.label}"`;
92 }
93
94 throw this.raise(pos != null ? pos : this.state.start, messageOrType);
95 }
96
97 expectPlugin(name, pos) {
98 if (!this.hasPlugin(name)) {
99 throw this.raiseWithData(pos != null ? pos : this.state.start, {
100 missingPlugin: [name]
101 }, `This experimental syntax requires enabling the parser plugin: '${name}'`);
102 }
103
104 return true;
105 }
106
107 expectOnePlugin(names, pos) {
108 if (!names.some(n => this.hasPlugin(n))) {
109 throw this.raiseWithData(pos != null ? pos : this.state.start, {
110 missingPlugin: names
111 }, `This experimental syntax requires enabling one of the following parser plugin(s): '${names.join(", ")}'`);
112 }
113 }
114
115 tryParse(fn, oldState = this.state.clone()) {
116 const abortSignal = {
117 node: null
118 };
119
120 try {
121 const node = fn((node = null) => {
122 abortSignal.node = node;
123 throw abortSignal;
124 });
125
126 if (this.state.errors.length > oldState.errors.length) {
127 const failState = this.state;
128 this.state = oldState;
129 return {
130 node,
131 error: failState.errors[oldState.errors.length],
132 thrown: false,
133 aborted: false,
134 failState
135 };
136 }
137
138 return {
139 node,
140 error: null,
141 thrown: false,
142 aborted: false,
143 failState: null
144 };
145 } catch (error) {
146 const failState = this.state;
147 this.state = oldState;
148
149 if (error instanceof SyntaxError) {
150 return {
151 node: null,
152 error,
153 thrown: true,
154 aborted: false,
155 failState
156 };
157 }
158
159 if (error === abortSignal) {
160 return {
161 node: abortSignal.node,
162 error: null,
163 thrown: false,
164 aborted: true,
165 failState
166 };
167 }
168
169 throw error;
170 }
171 }
172
173 checkExpressionErrors(refExpressionErrors, andThrow) {
174 if (!refExpressionErrors) return false;
175 const {
176 shorthandAssign,
177 doubleProto
178 } = refExpressionErrors;
179 if (!andThrow) return shorthandAssign >= 0 || doubleProto >= 0;
180
181 if (shorthandAssign >= 0) {
182 this.unexpected(shorthandAssign);
183 }
184
185 if (doubleProto >= 0) {
186 this.raise(doubleProto, _error.Errors.DuplicateProto);
187 }
188 }
189
190 isLiteralPropertyName() {
191 return this.match(_types.types.name) || !!this.state.type.keyword || this.match(_types.types.string) || this.match(_types.types.num) || this.match(_types.types.bigint) || this.match(_types.types.decimal);
192 }
193
194}
195
196exports.default = UtilParser;
197
198class ExpressionErrors {
199 constructor() {
200 this.shorthandAssign = -1;
201 this.doubleProto = -1;
202 }
203
204}
205
206exports.ExpressionErrors = ExpressionErrors;
\No newline at end of file