/src/moddable/xs/sources/xsLexical.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016-2025 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsScript.h" |
39 | | |
40 | | static txU4 fxGetNextCode(txParser* parser); |
41 | | static txString fxGetNextDigits(txParser* parser, txString (*f)(txParser*, txString, txString), txString p, txString q, int empty); |
42 | | static txString fxGetNextDigitsB(txParser* parser, txString p, txString q); |
43 | | static txString fxGetNextDigitsD(txParser* parser, txString p, txString q, int* base); |
44 | | static txString fxGetNextDigitsE(txParser* parser, txString p, txString q); |
45 | | static txString fxGetNextDigitsO(txParser* parser, txString p, txString q); |
46 | | static txString fxGetNextDigitsX(txParser* parser, txString p, txString q); |
47 | | static void fxGetNextKeyword(txParser* parser); |
48 | | static txBoolean fxGetNextIdentiferX(txParser* parser, txU4* value); |
49 | | static void fxGetNextNumber(txParser* parser, txNumber theNumber); |
50 | | static void fxGetNextNumberB(txParser* parser); |
51 | | static void fxGetNextNumberE(txParser* parser, int parseDot); |
52 | | static void fxGetNextNumberO(txParser* parser, int c, int i); |
53 | | static void fxGetNextNumberX(txParser* parser); |
54 | | static void fxGetNextString(txParser* parser, int c); |
55 | | static txBoolean fxGetNextStringD(int c, txU4* value); |
56 | | static txBoolean fxGetNextStringX(int c, txU4* value); |
57 | | static void fxGetNextTokenAux(txParser* parser); |
58 | | |
59 | 3.05M | #define XS_KEYWORD_COUNT 36 |
60 | | static const txKeyword ICACHE_RODATA_ATTR gxKeywords[XS_KEYWORD_COUNT] = { |
61 | | { "break", XS_TOKEN_BREAK }, |
62 | | { "case", XS_TOKEN_CASE }, |
63 | | { "catch", XS_TOKEN_CATCH }, |
64 | | { "class", XS_TOKEN_CLASS }, |
65 | | { "const", XS_TOKEN_CONST }, |
66 | | { "continue", XS_TOKEN_CONTINUE }, |
67 | | { "debugger", XS_TOKEN_DEBUGGER }, |
68 | | { "default", XS_TOKEN_DEFAULT }, |
69 | | { "delete", XS_TOKEN_DELETE }, |
70 | | { "do", XS_TOKEN_DO }, |
71 | | { "else", XS_TOKEN_ELSE }, |
72 | | { "enum", XS_TOKEN_ENUM }, |
73 | | { "export", XS_TOKEN_EXPORT }, |
74 | | { "extends", XS_TOKEN_EXTENDS }, |
75 | | { "false", XS_TOKEN_FALSE }, |
76 | | { "finally", XS_TOKEN_FINALLY }, |
77 | | { "for", XS_TOKEN_FOR }, |
78 | | { "function", XS_TOKEN_FUNCTION }, |
79 | | { "if", XS_TOKEN_IF }, |
80 | | { "import", XS_TOKEN_IMPORT }, |
81 | | { "in", XS_TOKEN_IN }, |
82 | | { "instanceof", XS_TOKEN_INSTANCEOF }, |
83 | | { "new", XS_TOKEN_NEW }, |
84 | | { "null", XS_TOKEN_NULL }, |
85 | | { "return", XS_TOKEN_RETURN }, |
86 | | { "super", XS_TOKEN_SUPER }, |
87 | | { "switch", XS_TOKEN_SWITCH }, |
88 | | { "this", XS_TOKEN_THIS }, |
89 | | { "throw", XS_TOKEN_THROW }, |
90 | | { "true", XS_TOKEN_TRUE }, |
91 | | { "try", XS_TOKEN_TRY }, |
92 | | { "typeof", XS_TOKEN_TYPEOF }, |
93 | | { "var", XS_TOKEN_VAR }, |
94 | | { "void", XS_TOKEN_VOID }, |
95 | | { "while", XS_TOKEN_WHILE }, |
96 | | { "with", XS_TOKEN_WITH } |
97 | | }; |
98 | | |
99 | 198k | #define XS_STRICT_KEYWORD_COUNT 9 |
100 | | static const txKeyword ICACHE_RODATA_ATTR gxStrictKeywords[XS_STRICT_KEYWORD_COUNT] = { |
101 | | { "implements", XS_TOKEN_IMPLEMENTS }, |
102 | | { "interface", XS_TOKEN_INTERFACE }, |
103 | | { "let", XS_TOKEN_LET }, |
104 | | { "package", XS_TOKEN_PACKAGE }, |
105 | | { "private", XS_TOKEN_PRIVATE }, |
106 | | { "protected", XS_TOKEN_PROTECTED }, |
107 | | { "public", XS_TOKEN_PUBLIC }, |
108 | | { "static", XS_TOKEN_STATIC }, |
109 | | { "yield", XS_TOKEN_YIELD } |
110 | | }; |
111 | | |
112 | | static txString fxUTF8Buffer(txParser* parser, txInteger character, txString string, txString limit) |
113 | 38.3M | { |
114 | 38.3M | if (string + mxStringByteLength(character) > limit) { |
115 | 34 | fxReportMemoryError(parser, parser->states[2].line, "buffer overflow"); |
116 | 34 | } |
117 | 38.3M | return mxStringByteEncode(string, character); |
118 | 38.3M | } |
119 | | |
120 | | void fxCheckStrictKeyword(txParser* parser) |
121 | 13.8k | { |
122 | 13.8k | int low, high, anIndex, aDelta; |
123 | 49.7k | for (low = 0, high = XS_STRICT_KEYWORD_COUNT; high > low; |
124 | 39.4k | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
125 | 39.4k | anIndex = low + ((high - low) / 2); |
126 | 39.4k | aDelta = c_strcmp(gxStrictKeywords[anIndex].text, parser->buffer); |
127 | 39.4k | if (aDelta == 0) { |
128 | 3.48k | parser->states[0].token = gxStrictKeywords[anIndex].token; |
129 | 3.48k | goto bail; |
130 | 3.48k | } |
131 | 39.4k | } |
132 | 13.8k | bail: |
133 | 13.8k | if (parser->states[0].escaped) |
134 | 0 | fxReportParserError(parser, parser->states[0].line, "escaped keyword"); |
135 | 13.8k | } |
136 | | |
137 | | void fxGetNextCharacter(txParser* parser) |
138 | 102M | { |
139 | 102M | parser->character = parser->lookahead; |
140 | 102M | if (parser->character != (txU4)C_EOF) { |
141 | 102M | #if mxCESU8 |
142 | 102M | txU4 character = parser->surrogate; |
143 | 102M | if (character) |
144 | 11.0k | parser->surrogate = 0; |
145 | 102M | else |
146 | 102M | character = fxGetNextCode(parser); |
147 | 102M | if ((0x0000D800 <= character) && (character <= 0x0000DBFF)) { |
148 | 42.9k | txU4 surrogate = fxGetNextCode(parser); |
149 | 42.9k | if ((0x0000DC00 <= surrogate) && (surrogate <= 0x0000DFFF)) |
150 | 31.8k | character = 0x00010000 + ((character & 0x000003FF) << 10) + (surrogate & 0x000003FF); |
151 | 11.0k | else |
152 | 11.0k | parser->surrogate = surrogate; |
153 | 42.9k | } |
154 | 102M | parser->lookahead = character; |
155 | | #else |
156 | | parser->lookahead = fxGetNextCode(parser); |
157 | | #endif |
158 | 102M | } |
159 | 102M | } |
160 | | |
161 | | txU4 fxGetNextCode(txParser* parser) |
162 | 102M | { |
163 | 102M | txU4 code = (txU4)(*(parser->getter))(parser->stream); |
164 | 102M | if ((code & 0x80) && (code != (txU4)C_EOF)) { |
165 | 19.8M | txUTF8Sequence const *sequence = NULL; |
166 | 51.7M | for (sequence = gxUTF8Sequences; sequence->size; sequence++) { |
167 | 51.7M | if ((code & sequence->cmask) == sequence->cval) |
168 | 19.8M | break; |
169 | 51.7M | } |
170 | 19.8M | if (sequence->size == 0) { |
171 | 0 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", code); |
172 | 0 | code = (txU4)C_EOF; |
173 | 0 | } |
174 | 19.8M | else { |
175 | 19.8M | txS4 size = sequence->size - 1; |
176 | 51.7M | while (size) { |
177 | 31.8M | size--; |
178 | 31.8M | code = (code << 6) | ((*(parser->getter))(parser->stream) & 0x3F); |
179 | 31.8M | } |
180 | 19.8M | code &= sequence->lmask; |
181 | 19.8M | } |
182 | 19.8M | if (code == 0x000110000) |
183 | 0 | code = 0; |
184 | 19.8M | } |
185 | 102M | return code; |
186 | 102M | } |
187 | | |
188 | | txString fxGetNextDigits(txParser* parser, txString (*f)(txParser*, txString, txString), txString p, txString q, int empty) |
189 | 588k | { |
190 | 588k | int separator = 0; |
191 | 590k | for (;;) { |
192 | 590k | txString r = p; |
193 | 590k | p = (*f)(parser, p, q); |
194 | 590k | if (r < p) { |
195 | 566k | empty = 0; |
196 | 566k | separator = 0; |
197 | 566k | if (parser->character == '_') { |
198 | 2.65k | fxGetNextCharacter(parser); |
199 | 2.65k | separator = 1; |
200 | 2.65k | } |
201 | 563k | else |
202 | 563k | break; |
203 | 566k | } |
204 | 24.5k | else |
205 | 24.5k | break; |
206 | 590k | } |
207 | 588k | if (empty || separator) |
208 | 10.6k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
209 | 588k | return p; |
210 | 588k | } |
211 | | |
212 | | txString fxGetNextDigitsB(txParser* parser, txString p, txString q) |
213 | 3.87k | { |
214 | 3.87k | int c = parser->character; |
215 | 7.10k | while (('0' <= c) && (c <= '1')) { |
216 | 3.22k | if (p < q) *p++ = (char)c; |
217 | 3.22k | fxGetNextCharacter(parser); |
218 | 3.22k | c = parser->character; |
219 | 3.22k | } |
220 | 3.87k | return p; |
221 | 3.87k | } |
222 | | |
223 | | txString fxGetNextDigitsD(txParser* parser, txString p, txString q, int* base) |
224 | 7.00k | { |
225 | 7.00k | int c = parser->character; |
226 | 7.00k | *base = 8; |
227 | 311k | while (('0' <= c) && (c <= '9')) { |
228 | 304k | if (p < q) *p++ = (char)c; |
229 | 304k | if (('8' <= c) && (c <= '9')) |
230 | 3.13k | *base = 10; |
231 | 304k | fxGetNextCharacter(parser); |
232 | 304k | c = parser->character; |
233 | 304k | } |
234 | 7.00k | return p; |
235 | 7.00k | } |
236 | | |
237 | | txString fxGetNextDigitsE(txParser* parser, txString p, txString q) |
238 | 456k | { |
239 | 456k | int c = parser->character; |
240 | 3.86M | while (('0' <= c) && (c <= '9')) { |
241 | 3.40M | if (p < q) *p++ = (char)c; |
242 | 3.40M | fxGetNextCharacter(parser); |
243 | 3.40M | c = parser->character; |
244 | 3.40M | } |
245 | 456k | return p; |
246 | 456k | } |
247 | | |
248 | | txString fxGetNextDigitsO(txParser* parser, txString p, txString q) |
249 | 1.35k | { |
250 | 1.35k | int c = parser->character; |
251 | 5.80k | while (('0' <= c) && (c <= '7')) { |
252 | 4.45k | if (p < q) *p++ = (char)c; |
253 | 4.45k | fxGetNextCharacter(parser); |
254 | 4.45k | c = parser->character; |
255 | 4.45k | } |
256 | 1.35k | return p; |
257 | 1.35k | } |
258 | | |
259 | | txString fxGetNextDigitsX(txParser* parser, txString p, txString q) |
260 | 128k | { |
261 | 128k | int c = parser->character; |
262 | 971k | while ((('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'))) { |
263 | 843k | if (p < q) *p++ = (char)c; |
264 | 843k | fxGetNextCharacter(parser); |
265 | 843k | c = parser->character; |
266 | 843k | } |
267 | 128k | return p; |
268 | 128k | } |
269 | | |
270 | | void fxGetNextKeyword(txParser* parser) |
271 | 3.33M | { |
272 | 3.33M | int low, high, anIndex, aDelta; |
273 | | |
274 | 3.33M | parser->states[2].symbol = fxNewParserSymbol(parser, parser->buffer); |
275 | 3.33M | parser->states[2].token = XS_TOKEN_IDENTIFIER; |
276 | 3.33M | if ((parser->states[0].token == XS_TOKEN_DOT) || (parser->states[0].token == XS_TOKEN_CHAIN)) |
277 | 284k | return; |
278 | 17.9M | for (low = 0, high = XS_KEYWORD_COUNT; high > low; |
279 | 15.7M | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
280 | 15.7M | anIndex = low + ((high - low) / 2); |
281 | 15.7M | aDelta = c_strcmp(gxKeywords[anIndex].text, parser->buffer); |
282 | 15.7M | if (aDelta == 0) { |
283 | 804k | parser->states[2].token = gxKeywords[anIndex].token; |
284 | 804k | return; |
285 | 804k | } |
286 | 15.7M | } |
287 | 2.24M | if ((parser->flags & mxStrictFlag)) { |
288 | 720k | for (low = 0, high = XS_STRICT_KEYWORD_COUNT; high > low; |
289 | 588k | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
290 | 588k | anIndex = low + ((high - low) / 2); |
291 | 588k | aDelta = c_strcmp(gxStrictKeywords[anIndex].text, parser->buffer); |
292 | 588k | if (aDelta == 0) { |
293 | 53.1k | parser->states[2].token = gxStrictKeywords[anIndex].token; |
294 | 53.1k | return; |
295 | 53.1k | } |
296 | 588k | } |
297 | 184k | } |
298 | 2.19M | if (c_strcmp("await", parser->buffer) == 0) { |
299 | 2.65k | if (parser->flags & mxAsyncFlag) { |
300 | 2.26k | parser->states[2].token = XS_TOKEN_AWAIT; |
301 | 2.26k | return; |
302 | 2.26k | } |
303 | 2.65k | } |
304 | 2.19M | if (c_strcmp("yield", parser->buffer) == 0) { |
305 | 7.87k | if ((parser->flags & mxGeneratorFlag)){ |
306 | 1.90k | parser->states[2].token = XS_TOKEN_YIELD; |
307 | 1.90k | return; |
308 | 1.90k | } |
309 | 7.87k | } |
310 | 2.18M | return; |
311 | 2.19M | } |
312 | | |
313 | | txBoolean fxGetNextIdentiferX(txParser* parser, txU4* value) |
314 | 9.81k | { |
315 | 9.81k | fxGetNextCharacter(parser); |
316 | 9.81k | if (parser->character == 'u') { |
317 | 8.64k | fxGetNextCharacter(parser); |
318 | 8.64k | if (parser->character == '{') { |
319 | 2.07k | fxGetNextCharacter(parser); |
320 | 20.5k | while (fxGetNextStringX(parser->character, value)) { |
321 | 18.4k | fxGetNextCharacter(parser); |
322 | 18.4k | } |
323 | 2.07k | if (parser->character == '}') { |
324 | 157 | fxGetNextCharacter(parser); |
325 | 157 | return 1; |
326 | 157 | } |
327 | 2.07k | } |
328 | 6.57k | else { |
329 | 6.57k | if (fxGetNextStringX(parser->character, value)) { |
330 | 3.46k | fxGetNextCharacter(parser); |
331 | 3.46k | if (fxGetNextStringX(parser->character, value)) { |
332 | 3.31k | fxGetNextCharacter(parser); |
333 | 3.31k | if (fxGetNextStringX(parser->character, value)) { |
334 | 2.70k | fxGetNextCharacter(parser); |
335 | 2.70k | if (fxGetNextStringX(parser->character, value)) { |
336 | 1.19k | fxGetNextCharacter(parser); |
337 | 1.19k | return 1; |
338 | 1.19k | } |
339 | 2.70k | } |
340 | 3.31k | } |
341 | 3.46k | } |
342 | 6.57k | } |
343 | 8.64k | } |
344 | 8.46k | return 0; |
345 | 9.81k | } |
346 | | |
347 | | void fxGetNextNumber(txParser* parser, txNumber theNumber) |
348 | 488k | { |
349 | 488k | parser->states[2].number = theNumber; |
350 | 488k | parser->states[2].integer = (txInteger)parser->states[2].number; |
351 | 488k | theNumber = parser->states[2].integer; |
352 | 488k | if (parser->states[2].number == theNumber) |
353 | 438k | parser->states[2].token = XS_TOKEN_INTEGER; |
354 | 49.9k | else |
355 | 49.9k | parser->states[2].token = XS_TOKEN_NUMBER; |
356 | 488k | } |
357 | | |
358 | | void fxGetNextNumberB(txParser* parser) |
359 | 3.85k | { |
360 | 3.85k | txString p = parser->buffer; |
361 | 3.85k | txString q = p + parser->bufferSize; |
362 | 3.85k | int c; |
363 | 3.85k | fxGetNextCharacter(parser); |
364 | 3.85k | p = fxGetNextDigits(parser, fxGetNextDigitsB, p, q, 1); |
365 | 3.85k | c = parser->character; |
366 | 3.85k | if (p == q) { |
367 | 0 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
368 | 0 | } |
369 | 3.85k | if (c == 'n') |
370 | 44 | fxGetNextCharacter(parser); |
371 | 3.85k | if (fxIsIdentifierFirst(parser->character)) { |
372 | 58 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
373 | 58 | } |
374 | 3.85k | *p = 0; |
375 | 3.85k | q = parser->buffer; |
376 | 3.85k | if (c == 'n') { |
377 | 17 | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximumB(mxPtrDiff(p - q))); |
378 | 17 | fxBigIntParseB(&parser->states[2].bigint, q, mxPtrDiff(p - q)); |
379 | 17 | parser->states[2].token = XS_TOKEN_BIGINT; |
380 | 17 | } |
381 | 3.83k | else { |
382 | 3.83k | txNumber n = 0; |
383 | 5.10k | while ((c = *q++)) |
384 | 1.26k | n = (n * 2) + (c - '0'); |
385 | 3.83k | fxGetNextNumber(parser, n); |
386 | 3.83k | } |
387 | 3.85k | } |
388 | | |
389 | | void fxGetNextNumberE(txParser* parser, int dot) |
390 | 424k | { |
391 | 424k | txString p = parser->buffer; |
392 | 424k | txString q = p + parser->bufferSize; |
393 | 424k | txString r; |
394 | 424k | int c; |
395 | 424k | if (dot) { |
396 | 9.68k | if (p < q) *p++ = '.'; |
397 | 9.68k | } |
398 | 424k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 0); |
399 | 424k | if (dot) |
400 | 9.68k | r = p; |
401 | 414k | else if (parser->character == '.') { |
402 | 18.7k | dot = 1; |
403 | 18.7k | if (p < q) *p++ = '.'; |
404 | 18.7k | fxGetNextCharacter(parser); |
405 | 18.7k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 0); |
406 | 18.7k | r = p; |
407 | 18.7k | } |
408 | 424k | c = parser->character; |
409 | 424k | if ((c == 'e') || (c == 'E')) { |
410 | 10.9k | if (dot) { |
411 | 6.58k | if (p == r) { |
412 | 6.58k | if (p < q) *p++ = '0'; |
413 | 6.58k | } |
414 | 6.58k | } |
415 | 4.37k | else { |
416 | 4.37k | dot = 1; |
417 | 4.37k | if (p < q) *p++ = '.'; |
418 | 4.37k | if (p < q) *p++ = '0'; |
419 | 4.37k | } |
420 | 10.9k | if (p < q) *p++ = (char)c; |
421 | 10.9k | fxGetNextCharacter(parser); |
422 | 10.9k | c = parser->character; |
423 | 10.9k | if ((c == '+') || (c == '-')) { |
424 | 2.78k | if (p < q) *p++ = (char)c; |
425 | 2.78k | fxGetNextCharacter(parser); |
426 | 2.78k | c = parser->character; |
427 | 2.78k | } |
428 | 10.9k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 1); |
429 | 10.9k | c = parser->character; |
430 | 10.9k | } |
431 | 424k | if (p == q) { |
432 | 9 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
433 | 9 | } |
434 | 424k | if (c == 'n') |
435 | 55.4k | fxGetNextCharacter(parser); |
436 | 424k | if (fxIsIdentifierFirst(parser->character)) { |
437 | 6.20k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
438 | 6.20k | } |
439 | 424k | *p = 0; |
440 | 424k | q = parser->buffer; |
441 | 424k | if (c == 'n') { |
442 | 55.0k | if (dot == 0) { |
443 | 54.6k | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximum(mxPtrDiff(p - q))); |
444 | 54.6k | fxBigIntParse(&parser->states[2].bigint, q, mxPtrDiff(p - q), 0); |
445 | 54.6k | parser->states[2].token = XS_TOKEN_BIGINT; |
446 | 54.6k | } |
447 | 375 | else |
448 | 375 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
449 | 55.0k | } |
450 | 369k | else |
451 | 369k | fxGetNextNumber(parser, fxStringToNumber(parser->console, parser->buffer, 1)); |
452 | 424k | } |
453 | | |
454 | | void fxGetNextNumberO(txParser* parser, int c, int legacy) |
455 | 8.35k | { |
456 | 8.35k | txString p = parser->buffer; |
457 | 8.35k | txString q = p + parser->bufferSize; |
458 | 8.35k | if (legacy) { |
459 | 7.00k | p = fxGetNextDigitsD(parser, p, q, &legacy); |
460 | 7.00k | if (parser->character == '_') |
461 | 391 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
462 | 7.00k | if (parser->character == 'n') |
463 | 1.57k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
464 | 7.00k | } |
465 | 1.34k | else { |
466 | 1.34k | fxGetNextCharacter(parser); |
467 | 1.34k | legacy = 8; |
468 | 1.34k | p = fxGetNextDigits(parser, fxGetNextDigitsO, p, q, 1); |
469 | 1.34k | } |
470 | 8.35k | c = parser->character; |
471 | 8.35k | if (p == q) { |
472 | 1 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
473 | 1 | } |
474 | 8.35k | if (c == 'n') |
475 | 312 | fxGetNextCharacter(parser); |
476 | 8.35k | if (fxIsIdentifierFirst(parser->character)) { |
477 | 1.51k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
478 | 1.51k | } |
479 | 8.35k | *p = 0; |
480 | 8.35k | q = parser->buffer; |
481 | 8.35k | if (c == 'n') { |
482 | 312 | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximumO(mxPtrDiff(p - q))); |
483 | 312 | fxBigIntParseO(&parser->states[2].bigint, q, mxPtrDiff(p - q)); |
484 | 312 | parser->states[2].token = XS_TOKEN_BIGINT; |
485 | 312 | } |
486 | 8.03k | else { |
487 | 8.03k | txNumber n = 0; |
488 | 214k | while ((c = *q++)) |
489 | 206k | n = (n * legacy) + (c - '0'); |
490 | 8.03k | fxGetNextNumber(parser, n); |
491 | 8.03k | } |
492 | 8.35k | } |
493 | | |
494 | | void fxGetNextNumberX(txParser* parser) |
495 | 128k | { |
496 | 128k | txString p = parser->buffer; |
497 | 128k | txString q = p + parser->bufferSize; |
498 | 128k | int c; |
499 | 128k | fxGetNextCharacter(parser); |
500 | 128k | p = fxGetNextDigits(parser, fxGetNextDigitsX, p, q, 1); |
501 | 128k | c = parser->character; |
502 | 128k | if (p == q) { |
503 | 4 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
504 | 4 | } |
505 | 128k | if (c == 'n') |
506 | 512 | fxGetNextCharacter(parser); |
507 | 128k | if (fxIsIdentifierFirst(parser->character)) { |
508 | 1.05k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
509 | 1.05k | } |
510 | 128k | *p = 0; |
511 | 128k | q = parser->buffer; |
512 | 128k | if (c == 'n') { |
513 | 511 | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximumX(mxPtrDiff(p - q))); |
514 | 511 | fxBigIntParseX(&parser->states[2].bigint, q, mxPtrDiff(p - q)); |
515 | 511 | parser->states[2].token = XS_TOKEN_BIGINT; |
516 | 511 | } |
517 | 128k | else { |
518 | 128k | txNumber n = 0; |
519 | 666k | while ((c = *q++)) { |
520 | 538k | if (('0' <= c) && (c <= '9')) |
521 | 422k | n = (n * 16) + (c - '0'); |
522 | 115k | else if (('a' <= c) && (c <= 'f')) |
523 | 684 | n = (n * 16) + (10 + c - 'a'); |
524 | 115k | else |
525 | 115k | n = (n * 16) + (10 + c - 'A'); |
526 | 538k | } |
527 | 128k | fxGetNextNumber(parser, n); |
528 | 128k | } |
529 | 128k | } |
530 | | |
531 | | void fxGetNextRegExp(txParser* parser, txU4 c) |
532 | 23.1k | { |
533 | 23.1k | txString p; |
534 | 23.1k | txString q; |
535 | 23.1k | txBoolean backslash = 0; |
536 | 23.1k | txBoolean bracket = 0; |
537 | 23.1k | txBoolean first = 1; |
538 | 23.1k | txBoolean second = 1; |
539 | 23.1k | p = parser->buffer; |
540 | 23.1k | q = p + parser->bufferSize - 1; |
541 | 23.1k | if (!c) { |
542 | 22.5k | c = parser->character; |
543 | 22.5k | second = 0; |
544 | 22.5k | } |
545 | 1.87M | for (;;) { |
546 | 1.87M | if (c == (txU4)C_EOF) { |
547 | 3.81k | fxReportParserError(parser, parser->states[0].line, "end of file in regular expression"); |
548 | 3.81k | break; |
549 | 3.81k | } |
550 | 1.87M | else if ((c == 10) || (c == 13) || (c == 0x2028) || (c == 0x2029)) { |
551 | 2.65k | fxReportParserError(parser, parser->states[0].line, "end of line in regular expression"); |
552 | 2.65k | break; |
553 | 2.65k | } |
554 | 1.86M | else if (c == '*') { |
555 | 1.24k | if (first) { |
556 | 1 | fxReportParserError(parser, parser->states[0].line, "invalid regular expression"); |
557 | 1 | break; |
558 | 1 | } |
559 | 1.24k | backslash = 0; |
560 | 1.24k | } |
561 | 1.86M | else if (c == '\\') { |
562 | 155k | if (!backslash) |
563 | 94.3k | backslash = 1; |
564 | 60.8k | else |
565 | 60.8k | backslash = 0; |
566 | 155k | } |
567 | 1.71M | else if (c == '[') { |
568 | 43.1k | if (!backslash) |
569 | 39.6k | bracket = 1; |
570 | 43.1k | backslash = 0; |
571 | 43.1k | } |
572 | 1.66M | else if (c == ']') { |
573 | 13.4k | if (!backslash) |
574 | 13.2k | bracket = 0; |
575 | 13.4k | backslash = 0; |
576 | 13.4k | } |
577 | 1.65M | else if (c == '/') { |
578 | 19.9k | if (!backslash && !bracket) |
579 | 16.6k | break; |
580 | 3.23k | backslash = 0; |
581 | 3.23k | } |
582 | 1.63M | else { |
583 | 1.63M | backslash = 0; |
584 | 1.63M | } |
585 | 1.85M | p = fxUTF8Buffer(parser, c, p, q); |
586 | 1.85M | if (second) |
587 | 635 | second = 0; |
588 | 1.85M | else |
589 | 1.85M | fxGetNextCharacter(parser); |
590 | 1.85M | c = parser->character; |
591 | 1.85M | first = 0; |
592 | 1.85M | } |
593 | 23.1k | *p = 0; |
594 | 23.1k | parser->states[0].stringLength = mxPtrDiff(p - parser->buffer); |
595 | 23.1k | parser->states[0].string = fxNewParserString(parser, parser->buffer, parser->states[0].stringLength); |
596 | 23.1k | p = parser->buffer; |
597 | 23.1k | q = p + parser->bufferSize - 1; |
598 | 93.7k | for (;;) { |
599 | 93.7k | fxGetNextCharacter(parser); |
600 | 93.7k | if (fxIsIdentifierNext(parser->character)) |
601 | 77.0k | p = fxUTF8Buffer(parser, parser->character, p, q); |
602 | 16.6k | else |
603 | 16.6k | break; |
604 | 93.7k | } |
605 | 23.1k | *p = 0; |
606 | 23.1k | parser->states[0].modifierLength = mxPtrDiff(p - parser->buffer); |
607 | 23.1k | parser->states[0].modifier = fxNewParserString(parser, parser->buffer, parser->states[0].modifierLength); |
608 | 23.1k | if (!fxCompileRegExp(parser->console, parser->states[0].string, parser->states[0].modifier, C_NULL, C_NULL, parser->buffer, parser->bufferSize)) |
609 | 5.82k | fxReportParserError(parser, parser->states[0].line, "%s", parser->buffer); |
610 | 23.1k | parser->states[0].token = XS_TOKEN_REGEXP; |
611 | 23.1k | } |
612 | | |
613 | | void fxGetNextString(txParser* parser, int c) |
614 | 696k | { |
615 | 696k | txString p = parser->buffer; |
616 | 696k | txString q = p + parser->bufferSize - 1; |
617 | 18.7M | for (;;) { |
618 | 18.7M | if (parser->character == (txU4)C_EOF) { |
619 | 3.20k | fxReportParserError(parser, parser->states[2].line, "end of file in string"); |
620 | 3.20k | break; |
621 | 3.20k | } |
622 | 18.7M | else if (parser->character == 10) { |
623 | 133k | parser->states[2].line++; |
624 | 133k | if (c == '`') { |
625 | 128k | p = fxUTF8Buffer(parser, parser->character, p, q); |
626 | 128k | fxGetNextCharacter(parser); |
627 | 128k | } |
628 | 5.16k | else { |
629 | 5.16k | fxReportParserError(parser, parser->states[2].line, "end of line in string"); |
630 | 5.16k | break; |
631 | 5.16k | } |
632 | 133k | } |
633 | 18.6M | else if (parser->character == 13) { |
634 | 61.2k | parser->states[2].line++; |
635 | 61.2k | if (c == '`') { |
636 | 60.7k | p = fxUTF8Buffer(parser, 10, p, q); |
637 | 60.7k | fxGetNextCharacter(parser); |
638 | 60.7k | if (parser->character == 10) |
639 | 32.4k | fxGetNextCharacter(parser); |
640 | 60.7k | } |
641 | 455 | else { |
642 | 455 | fxReportParserError(parser, parser->states[2].line, "end of line in string"); |
643 | 455 | break; |
644 | 455 | } |
645 | 61.2k | } |
646 | 18.5M | else if ((parser->character == 0x2028) || (parser->character == 0x2029)) { |
647 | 1.39k | parser->states[2].line++; |
648 | 1.39k | p = fxUTF8Buffer(parser, parser->character, p, q); |
649 | 1.39k | fxGetNextCharacter(parser); |
650 | 1.39k | } |
651 | 18.5M | else if (parser->character == (txU4)c) { |
652 | 682k | break; |
653 | 682k | } |
654 | 17.8M | else if (parser->character == '$') { |
655 | 28.3k | fxGetNextCharacter(parser); |
656 | 28.3k | if ((c == '`') && (parser->character == '{')) |
657 | 4.85k | break; |
658 | 23.4k | p = fxUTF8Buffer(parser, '$', p, q); |
659 | 23.4k | } |
660 | 17.8M | else if (parser->character == '\\') { |
661 | 129k | parser->states[2].escaped = 1; |
662 | 129k | p = fxUTF8Buffer(parser, '\\', p, q); |
663 | 129k | fxGetNextCharacter(parser); |
664 | 129k | switch (parser->character) { |
665 | 1.08k | case 10: |
666 | 1.54k | case 0x2028: |
667 | 1.63k | case 0x2029: |
668 | 1.63k | parser->states[2].line++; |
669 | 1.63k | p = fxUTF8Buffer(parser, parser->character, p, q); |
670 | 1.63k | fxGetNextCharacter(parser); |
671 | 1.63k | break; |
672 | 918 | case 13: |
673 | 918 | parser->states[2].line++; |
674 | 918 | p = fxUTF8Buffer(parser, 10, p, q); |
675 | 918 | fxGetNextCharacter(parser); |
676 | 918 | if (parser->character == 10) |
677 | 225 | fxGetNextCharacter(parser); |
678 | 918 | break; |
679 | 126k | default: |
680 | 126k | p = fxUTF8Buffer(parser, parser->character, p, q); |
681 | 126k | fxGetNextCharacter(parser); |
682 | 126k | break; |
683 | 129k | } |
684 | 129k | } |
685 | 17.7M | else { |
686 | 17.7M | p = fxUTF8Buffer(parser, parser->character, p, q); |
687 | 17.7M | fxGetNextCharacter(parser); |
688 | 17.7M | } |
689 | 18.7M | } |
690 | 696k | *p = 0; |
691 | 696k | if (p == q) { |
692 | 0 | fxReportMemoryError(parser, parser->states[2].line, "string overflow"); |
693 | 0 | } |
694 | 696k | parser->states[2].rawLength = mxPtrDiff(p - parser->buffer); |
695 | 696k | parser->states[2].raw = fxNewParserString(parser, parser->buffer, parser->states[2].rawLength); |
696 | 696k | if (parser->states[2].escaped) { |
697 | 33.8k | txInteger character; |
698 | 33.8k | txString s; |
699 | 33.8k | txU1* u; |
700 | 33.8k | p = parser->buffer; |
701 | 33.8k | q = p + parser->bufferSize - 1; |
702 | 33.8k | s = parser->states[2].raw; |
703 | 15.9M | while (*s) { |
704 | 15.8M | if (p == q) { |
705 | 0 | fxReportMemoryError(parser, parser->states[2].line, "buffer overflow"); |
706 | 0 | } |
707 | 15.8M | if (*s == '\\') { |
708 | 122k | s++; |
709 | 122k | switch (*s) { |
710 | 0 | case 0: |
711 | 0 | break; |
712 | 1.46k | case 10: |
713 | 1.46k | s++; |
714 | 1.46k | break; |
715 | 0 | case 13: |
716 | 0 | s++; |
717 | 0 | if (*s == 10) |
718 | 0 | s++; |
719 | 0 | break; |
720 | 1.36k | case 'b': |
721 | 1.36k | s++; |
722 | 1.36k | *p++ = '\b'; |
723 | 1.36k | break; |
724 | 431 | case 'f': |
725 | 431 | s++; |
726 | 431 | *p++ = '\f'; |
727 | 431 | break; |
728 | 5.03k | case 'n': |
729 | 5.03k | s++; |
730 | 5.03k | *p++ = '\n'; |
731 | 5.03k | break; |
732 | 14.6k | case 'r': |
733 | 14.6k | s++; |
734 | 14.6k | *p++ = '\r'; |
735 | 14.6k | break; |
736 | 1.10k | case 't': |
737 | 1.10k | s++; |
738 | 1.10k | *p++ = '\t'; |
739 | 1.10k | break; |
740 | 335 | case 'v': |
741 | 335 | s++; |
742 | 335 | *p++ = '\v'; |
743 | 335 | break; |
744 | 684 | case 'x': |
745 | 684 | s++; |
746 | 684 | if (fxParseHexEscape(&s, &character)) |
747 | 644 | p = fxUTF8Buffer(parser, character, p, q); |
748 | 40 | else |
749 | 40 | parser->states[2].escaped |= mxStringErrorFlag; |
750 | 684 | break; |
751 | 33.8k | case 'u': |
752 | 33.8k | s++; |
753 | 33.8k | if (fxParseUnicodeEscape(&s, &character, 1, '\\')) |
754 | 24.8k | p = fxUTF8Buffer(parser, character, p, q); |
755 | 8.97k | else |
756 | 8.97k | parser->states[2].escaped |= mxStringErrorFlag; |
757 | 33.8k | break; |
758 | 1.22k | case '0': |
759 | 1.43k | case '1': |
760 | 1.63k | case '2': |
761 | 1.75k | case '3': |
762 | 1.85k | case '4': |
763 | 3.40k | case '5': |
764 | 3.50k | case '6': |
765 | 3.57k | case '7': |
766 | 3.57k | character = *s++ - '0'; |
767 | 3.57k | if ((character == 0) && ((*s < '0') || ('9' < *s))) |
768 | 1.09k | p = fxUTF8Buffer(parser, character, p, q); |
769 | 2.48k | else { |
770 | 2.48k | parser->states[2].escaped |= mxStringLegacyFlag; |
771 | 2.48k | if ((0 <= character) && (character <= 3)) { |
772 | 667 | if (('0' <= *s) && (*s <= '7')) |
773 | 227 | character = (character * 8) + *s++ - '0'; |
774 | 667 | } |
775 | 2.48k | if (('0' <= *s) && (*s <= '7')) |
776 | 155 | character = (character * 8) + *s++ - '0'; |
777 | 2.48k | p = fxUTF8Buffer(parser, character, p, q); |
778 | 2.48k | } |
779 | 3.57k | break; |
780 | 14 | case '8': |
781 | 123 | case '9': |
782 | 123 | parser->states[2].escaped |= mxStringLegacyFlag; |
783 | 123 | *p++ = *s++; |
784 | 123 | break; |
785 | 59.8k | default: |
786 | 59.8k | u = (txU1*)s; |
787 | 59.8k | if ((u[0] == 0xE2) && (u[1] == 0x80) && ((u[2] == 0xA8) || (u[2] == 0xA9))) { /* LS || PS */ |
788 | 507 | s += 3; |
789 | 507 | } |
790 | 59.3k | else |
791 | 59.3k | *p++ = *s++; |
792 | 59.8k | break; |
793 | 122k | } |
794 | 122k | } |
795 | 15.7M | else { |
796 | 15.7M | *p++ = *s++; |
797 | 15.7M | } |
798 | 15.8M | } |
799 | 33.8k | *p = 0; |
800 | 33.8k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
801 | 33.8k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
802 | 33.8k | if ((c == '`') && (parser->states[2].escaped & mxStringLegacyFlag)) |
803 | 1.83k | parser->states[2].escaped |= mxStringErrorFlag; |
804 | 33.8k | } |
805 | 662k | else { |
806 | 662k | parser->states[2].stringLength = parser->states[2].rawLength; |
807 | 662k | parser->states[2].string = parser->states[2].raw; |
808 | 662k | } |
809 | 696k | } |
810 | | |
811 | | txBoolean fxGetNextStringD(int c, txU4* value) |
812 | 1.37k | { |
813 | 1.37k | if (('0' <= c) && (c <= '9')) |
814 | 525 | *value = (*value * 10) + (c - '0'); |
815 | 850 | else |
816 | 850 | return 0; |
817 | 525 | return 1; |
818 | 1.37k | } |
819 | | |
820 | | txBoolean fxGetNextStringX(int c, txU4* value) |
821 | 48.3k | { |
822 | 48.3k | if (('0' <= c) && (c <= '9')) |
823 | 27.6k | *value = (*value * 16) + (c - '0'); |
824 | 20.6k | else if (('a' <= c) && (c <= 'f')) |
825 | 10.3k | *value = (*value * 16) + (10 + c - 'a'); |
826 | 10.2k | else if (('A' <= c) && (c <= 'F')) |
827 | 428 | *value = (*value * 16) + (10 + c - 'A'); |
828 | 9.81k | else |
829 | 9.81k | return 0; |
830 | 38.4k | return 1; |
831 | 48.3k | } |
832 | | |
833 | | void fxGetNextToken(txParser* parser) |
834 | 19.6M | { |
835 | 19.6M | if (parser->ahead == 0) { |
836 | 18.6M | fxGetNextTokenAux(parser); |
837 | 18.6M | parser->states[0] = parser->states[2]; |
838 | 18.6M | } |
839 | 1.07M | else if (parser->ahead == 1) { |
840 | 1.07M | parser->states[0] = parser->states[1]; |
841 | 1.07M | parser->ahead = 0; |
842 | 1.07M | } |
843 | 0 | else if (parser->ahead == 2) { |
844 | 0 | parser->states[0] = parser->states[1]; |
845 | 0 | parser->states[1] = parser->states[2]; |
846 | 0 | parser->ahead = 1; |
847 | 0 | } |
848 | 19.6M | } |
849 | | |
850 | | void fxLookAheadOnce(txParser* parser) |
851 | 1.13M | { |
852 | 1.13M | if (parser->ahead == 0) { |
853 | 1.13M | fxGetNextTokenAux(parser); |
854 | 1.13M | parser->states[1] = parser->states[2]; |
855 | 1.13M | parser->ahead = 1; |
856 | 1.13M | } |
857 | 1.13M | } |
858 | | |
859 | | void fxLookAheadTwice(txParser* parser) |
860 | 0 | { |
861 | 0 | if (parser->ahead == 0) { |
862 | 0 | fxGetNextTokenAux(parser); |
863 | 0 | parser->states[1] = parser->states[2]; |
864 | 0 | fxGetNextTokenAux(parser); |
865 | 0 | parser->ahead = 2; |
866 | 0 | } |
867 | 0 | else if (parser->ahead == 1) { |
868 | 0 | fxGetNextTokenAux(parser); |
869 | 0 | parser->ahead = 2; |
870 | 0 | } |
871 | 0 | } |
872 | | |
873 | | void fxGetNextTokenAux(txParser* parser) |
874 | 19.7M | { |
875 | 19.7M | int c; |
876 | 19.7M | txString p; |
877 | 19.7M | txString q; |
878 | 19.7M | txU4 t = 0; |
879 | 19.7M | parser->states[2].crlf = 0; |
880 | 19.7M | parser->states[2].escaped = 0; |
881 | 19.7M | parser->states[2].bigint.data = C_NULL; |
882 | 19.7M | parser->states[2].bigint.size = 0; |
883 | 19.7M | parser->states[2].bigint.sign = 0; |
884 | 19.7M | parser->states[2].integer = 0; |
885 | 19.7M | parser->states[2].modifierLength = 0; |
886 | 19.7M | parser->states[2].modifier = parser->emptyString; |
887 | 19.7M | parser->states[2].number = 0; |
888 | 19.7M | parser->states[2].rawLength = 0; |
889 | 19.7M | parser->states[2].raw = parser->emptyString; |
890 | 19.7M | parser->states[2].stringLength = 0; |
891 | 19.7M | parser->states[2].string = parser->emptyString; |
892 | 19.7M | parser->states[2].symbol = C_NULL; |
893 | 19.7M | parser->states[2].token = XS_NO_TOKEN; |
894 | 44.9M | while (parser->states[2].token == XS_NO_TOKEN) { |
895 | 25.3M | switch (parser->character) { |
896 | 268k | case C_EOF: |
897 | 268k | parser->states[2].token = XS_TOKEN_EOF; |
898 | 268k | break; |
899 | 1.93M | case 10: |
900 | 1.93M | case 0x2028: // <LS> |
901 | 1.93M | case 0x2029: // <PS> |
902 | 1.93M | parser->states[2].line++; |
903 | 1.93M | fxGetNextCharacter(parser); |
904 | 1.93M | parser->states[2].crlf = 1; |
905 | 1.93M | break; |
906 | 78.9k | case 13: |
907 | 78.9k | parser->states[2].line++; |
908 | 78.9k | fxGetNextCharacter(parser); |
909 | 78.9k | if (parser->character == 10) |
910 | 44.0k | fxGetNextCharacter(parser); |
911 | 78.9k | parser->states[2].crlf = 1; |
912 | 78.9k | break; |
913 | | |
914 | 199k | case '\t': |
915 | 340k | case 11: |
916 | 395k | case 12: |
917 | 3.17M | case ' ': |
918 | 3.17M | case 0x00A0: |
919 | 3.18M | case 0x1680: |
920 | 3.18M | case 0x2000: |
921 | 3.18M | case 0x2001: |
922 | 3.18M | case 0x2002: |
923 | 3.18M | case 0x2003: |
924 | 3.18M | case 0x2004: |
925 | 3.19M | case 0x2005: |
926 | 3.19M | case 0x2006: |
927 | 3.19M | case 0x2007: |
928 | 3.19M | case 0x2008: |
929 | 3.19M | case 0x2009: |
930 | 3.19M | case 0x200A: |
931 | 3.19M | case 0x202F: |
932 | 3.19M | case 0x205F: |
933 | 3.19M | case 0x3000: |
934 | 3.19M | case 0xFEFF: |
935 | 3.19M | fxGetNextCharacter(parser); |
936 | 3.19M | break; |
937 | | |
938 | 4.69M | case '0': |
939 | 4.69M | fxGetNextCharacter(parser); |
940 | 4.69M | c = parser->character; |
941 | 4.69M | if (c == '.') { |
942 | 13.0k | fxGetNextCharacter(parser); |
943 | 13.0k | c = parser->character; |
944 | 13.0k | if ((('0' <= c) && (c <= '9')) || (c == 'e') || (c == 'E')) |
945 | 4.83k | fxGetNextNumberE(parser, 1); |
946 | 8.18k | else { |
947 | 8.18k | parser->states[2].number = 0; |
948 | 8.18k | parser->states[2].token = XS_TOKEN_NUMBER; |
949 | 8.18k | } |
950 | 13.0k | } |
951 | 4.68M | else if ((c == 'b') || (c == 'B')) { |
952 | 3.85k | fxGetNextNumberB(parser); |
953 | 3.85k | } |
954 | 4.67M | else if ((c == 'e') || (c == 'E')) { |
955 | 1.89k | fxGetNextNumberE(parser, 0); |
956 | 1.89k | } |
957 | 4.67M | else if (c == 'n') { |
958 | 3.88k | fxGetNextNumberE(parser, 0); |
959 | 3.88k | } |
960 | 4.67M | else if ((c == 'o') || (c == 'O')) { |
961 | 1.34k | fxGetNextNumberO(parser, '0', 0); |
962 | 1.34k | } |
963 | 4.67M | else if ((c == 'x') || (c == 'X')) { |
964 | 128k | fxGetNextNumberX(parser); |
965 | 128k | } |
966 | 4.54M | else if (('0' <= c) && (c <= '9')) { |
967 | 7.15k | if ((parser->flags & mxStrictFlag)) |
968 | 153 | fxReportParserError(parser, parser->states[2].line, "octal number (strict mode)"); |
969 | 7.15k | fxGetNextNumberO(parser, c, 1); |
970 | 7.15k | } |
971 | 4.53M | else { |
972 | 4.53M | parser->states[2].integer = 0; |
973 | 4.53M | parser->states[2].token = XS_TOKEN_INTEGER; |
974 | 4.53M | } |
975 | 4.69M | break; |
976 | 127k | case '1': |
977 | 198k | case '2': |
978 | 281k | case '3': |
979 | 308k | case '4': |
980 | 325k | case '5': |
981 | 349k | case '6': |
982 | 360k | case '7': |
983 | 386k | case '8': |
984 | 408k | case '9': |
985 | 408k | fxGetNextNumberE(parser, 0); |
986 | 408k | break; |
987 | 301k | case '.': |
988 | 301k | fxGetNextCharacter(parser); |
989 | 301k | c = parser->character; |
990 | 301k | if (c == '.') { |
991 | 6.51k | fxGetNextCharacter(parser); |
992 | 6.51k | if (parser->character == '.') { |
993 | 5.20k | parser->states[2].token = XS_TOKEN_SPREAD; |
994 | 5.20k | fxGetNextCharacter(parser); |
995 | 5.20k | } |
996 | 1.31k | else { |
997 | 1.31k | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
998 | 1.31k | } |
999 | 6.51k | } |
1000 | 295k | else if (('0' <= c) && (c <= '9')) |
1001 | 4.85k | fxGetNextNumberE(parser, 1); |
1002 | 290k | else |
1003 | 290k | parser->states[2].token = XS_TOKEN_DOT; |
1004 | 301k | break; |
1005 | 691k | case ',': |
1006 | 691k | parser->states[2].token = XS_TOKEN_COMMA; |
1007 | 691k | fxGetNextCharacter(parser); |
1008 | 691k | break; |
1009 | 414k | case ';': |
1010 | 414k | parser->states[2].token = XS_TOKEN_SEMICOLON; |
1011 | 414k | fxGetNextCharacter(parser); |
1012 | 414k | break; |
1013 | 160k | case ':': |
1014 | 160k | parser->states[2].token = XS_TOKEN_COLON; |
1015 | 160k | fxGetNextCharacter(parser); |
1016 | 160k | break; |
1017 | 22.6k | case '?': |
1018 | 22.6k | fxGetNextCharacter(parser); |
1019 | 22.6k | if (parser->character == '.') { |
1020 | 7.06k | if ((parser->lookahead < '0') || ('9' < parser->lookahead)) { |
1021 | 6.67k | parser->states[2].token = XS_TOKEN_CHAIN; |
1022 | 6.67k | fxGetNextCharacter(parser); |
1023 | 6.67k | } |
1024 | 387 | else |
1025 | 387 | parser->states[2].token = XS_TOKEN_QUESTION_MARK; |
1026 | 7.06k | } |
1027 | 15.6k | else if (parser->character == '?') { |
1028 | 3.10k | parser->states[2].token = XS_TOKEN_COALESCE; |
1029 | 3.10k | fxGetNextCharacter(parser); |
1030 | 3.10k | if (parser->character == '=') { |
1031 | 415 | parser->states[2].token = XS_TOKEN_COALESCE_ASSIGN; |
1032 | 415 | fxGetNextCharacter(parser); |
1033 | 415 | } |
1034 | 3.10k | } |
1035 | 12.5k | else |
1036 | 12.5k | parser->states[2].token = XS_TOKEN_QUESTION_MARK; |
1037 | 22.6k | break; |
1038 | 917k | case '(': |
1039 | 917k | parser->states[2].token = XS_TOKEN_LEFT_PARENTHESIS; |
1040 | 917k | fxGetNextCharacter(parser); |
1041 | 917k | break; |
1042 | 703k | case ')': |
1043 | 703k | parser->states[2].token = XS_TOKEN_RIGHT_PARENTHESIS; |
1044 | 703k | fxGetNextCharacter(parser); |
1045 | 703k | break; |
1046 | 163k | case '[': |
1047 | 163k | parser->states[2].token = XS_TOKEN_LEFT_BRACKET; |
1048 | 163k | fxGetNextCharacter(parser); |
1049 | 163k | break; |
1050 | 149k | case ']': |
1051 | 149k | parser->states[2].token = XS_TOKEN_RIGHT_BRACKET; |
1052 | 149k | fxGetNextCharacter(parser); |
1053 | 149k | break; |
1054 | 605k | case '{': |
1055 | 605k | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1056 | 605k | fxGetNextCharacter(parser); |
1057 | 605k | break; |
1058 | 273k | case '}': |
1059 | 273k | parser->states[2].token = XS_TOKEN_RIGHT_BRACE; |
1060 | 273k | fxGetNextCharacter(parser); |
1061 | 273k | break; |
1062 | 300k | case '=': |
1063 | 300k | fxGetNextCharacter(parser); |
1064 | 300k | if (parser->character == '=') { |
1065 | 7.58k | fxGetNextCharacter(parser); |
1066 | 7.58k | if (parser->character == '=') { |
1067 | 4.50k | parser->states[2].token = XS_TOKEN_STRICT_EQUAL; |
1068 | 4.50k | fxGetNextCharacter(parser); |
1069 | 4.50k | } |
1070 | 3.07k | else |
1071 | 3.07k | parser->states[2].token = XS_TOKEN_EQUAL; |
1072 | 7.58k | } |
1073 | 292k | else if (parser->character == '>') { |
1074 | 91.0k | parser->states[2].token = XS_TOKEN_ARROW; |
1075 | 91.0k | fxGetNextCharacter(parser); |
1076 | 91.0k | } |
1077 | 201k | else |
1078 | 201k | parser->states[2].token = XS_TOKEN_ASSIGN; |
1079 | 300k | break; |
1080 | 88.4k | case '<': |
1081 | 88.4k | fxGetNextCharacter(parser); |
1082 | 88.4k | if (parser->character == '<') { |
1083 | 20.1k | fxGetNextCharacter(parser); |
1084 | 20.1k | if (parser->character == '=') { |
1085 | 194 | parser->states[2].token = XS_TOKEN_LEFT_SHIFT_ASSIGN; |
1086 | 194 | fxGetNextCharacter(parser); |
1087 | 194 | } |
1088 | 19.9k | else |
1089 | 19.9k | parser->states[2].token = XS_TOKEN_LEFT_SHIFT; |
1090 | 20.1k | } |
1091 | 68.3k | else if (parser->character == '=') { |
1092 | 1.46k | parser->states[2].token = XS_TOKEN_LESS_EQUAL; |
1093 | 1.46k | fxGetNextCharacter(parser); |
1094 | 1.46k | } |
1095 | 66.8k | else |
1096 | 66.8k | parser->states[2].token = XS_TOKEN_LESS; |
1097 | 88.4k | break; |
1098 | 85.6k | case '>': |
1099 | 85.6k | fxGetNextCharacter(parser); |
1100 | 85.6k | if (parser->character == '>') { |
1101 | 12.8k | fxGetNextCharacter(parser); |
1102 | 12.8k | if (parser->character == '>') { |
1103 | 4.80k | fxGetNextCharacter(parser); |
1104 | 4.80k | if (parser->character == '=') { |
1105 | 3.70k | parser->states[2].token = XS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGN; |
1106 | 3.70k | fxGetNextCharacter(parser); |
1107 | 3.70k | } |
1108 | 1.10k | else |
1109 | 1.10k | parser->states[2].token = XS_TOKEN_UNSIGNED_RIGHT_SHIFT; |
1110 | 4.80k | } |
1111 | 8.03k | else if (parser->character == '=') { |
1112 | 5.55k | parser->states[2].token = XS_TOKEN_SIGNED_RIGHT_SHIFT_ASSIGN; |
1113 | 5.55k | fxGetNextCharacter(parser); |
1114 | 5.55k | } |
1115 | 2.48k | else |
1116 | 2.48k | parser->states[2].token = XS_TOKEN_SIGNED_RIGHT_SHIFT; |
1117 | 12.8k | } |
1118 | 72.7k | else if (parser->character == '=') { |
1119 | 3.13k | parser->states[2].token = XS_TOKEN_MORE_EQUAL; |
1120 | 3.13k | fxGetNextCharacter(parser); |
1121 | 3.13k | } |
1122 | 69.6k | else |
1123 | 69.6k | parser->states[2].token = XS_TOKEN_MORE; |
1124 | 85.6k | break; |
1125 | 190k | case '!': |
1126 | 190k | fxGetNextCharacter(parser); |
1127 | 190k | if (parser->character == '=') { |
1128 | 2.47k | fxGetNextCharacter(parser); |
1129 | 2.47k | if (parser->character == '=') { |
1130 | 1.57k | parser->states[2].token = XS_TOKEN_STRICT_NOT_EQUAL; |
1131 | 1.57k | fxGetNextCharacter(parser); |
1132 | 1.57k | } |
1133 | 900 | else |
1134 | 900 | parser->states[2].token = XS_TOKEN_NOT_EQUAL; |
1135 | 2.47k | } |
1136 | 187k | else |
1137 | 187k | parser->states[2].token = XS_TOKEN_NOT; |
1138 | 190k | break; |
1139 | 4.78k | case '~': |
1140 | 4.78k | parser->states[2].token = XS_TOKEN_BIT_NOT; |
1141 | 4.78k | fxGetNextCharacter(parser); |
1142 | 4.78k | break; |
1143 | 56.1k | case '&': |
1144 | 56.1k | fxGetNextCharacter(parser); |
1145 | 56.1k | if (parser->character == '=') { |
1146 | 816 | parser->states[2].token = XS_TOKEN_BIT_AND_ASSIGN; |
1147 | 816 | fxGetNextCharacter(parser); |
1148 | 816 | } |
1149 | 55.2k | else if (parser->character == '&') { |
1150 | 15.9k | parser->states[2].token = XS_TOKEN_AND; |
1151 | 15.9k | fxGetNextCharacter(parser); |
1152 | 15.9k | if (parser->character == '=') { |
1153 | 1.99k | parser->states[2].token = XS_TOKEN_AND_ASSIGN; |
1154 | 1.99k | fxGetNextCharacter(parser); |
1155 | 1.99k | } |
1156 | 15.9k | } |
1157 | 39.3k | else |
1158 | 39.3k | parser->states[2].token = XS_TOKEN_BIT_AND; |
1159 | 56.1k | break; |
1160 | 14.2k | case '|': |
1161 | 14.2k | fxGetNextCharacter(parser); |
1162 | 14.2k | if (parser->character == '=') { |
1163 | 370 | parser->states[2].token = XS_TOKEN_BIT_OR_ASSIGN; |
1164 | 370 | fxGetNextCharacter(parser); |
1165 | 370 | } |
1166 | 13.9k | else if (parser->character == '|') { |
1167 | 4.93k | parser->states[2].token = XS_TOKEN_OR; |
1168 | 4.93k | fxGetNextCharacter(parser); |
1169 | 4.93k | if (parser->character == '=') { |
1170 | 820 | parser->states[2].token = XS_TOKEN_OR_ASSIGN; |
1171 | 820 | fxGetNextCharacter(parser); |
1172 | 820 | } |
1173 | 4.93k | } |
1174 | 8.99k | else |
1175 | 8.99k | parser->states[2].token = XS_TOKEN_BIT_OR; |
1176 | 14.2k | break; |
1177 | 7.36k | case '^': |
1178 | 7.36k | fxGetNextCharacter(parser); |
1179 | 7.36k | if (parser->character == '=') { |
1180 | 12 | parser->states[2].token = XS_TOKEN_BIT_XOR_ASSIGN; |
1181 | 12 | fxGetNextCharacter(parser); |
1182 | 12 | } |
1183 | 7.35k | else |
1184 | 7.35k | parser->states[2].token = XS_TOKEN_BIT_XOR; |
1185 | 7.36k | break; |
1186 | 98.7k | case '+': |
1187 | 98.7k | fxGetNextCharacter(parser); |
1188 | 98.7k | if (parser->character == '=') { |
1189 | 4.72k | parser->states[2].token = XS_TOKEN_ADD_ASSIGN; |
1190 | 4.72k | fxGetNextCharacter(parser); |
1191 | 4.72k | } |
1192 | 94.0k | else if (parser->character == '+') { |
1193 | 25.9k | parser->states[2].token = XS_TOKEN_INCREMENT; |
1194 | 25.9k | fxGetNextCharacter(parser); |
1195 | 25.9k | } |
1196 | 68.1k | else |
1197 | 68.1k | parser->states[2].token = XS_TOKEN_ADD; |
1198 | 98.7k | break; |
1199 | 4.70M | case '-': |
1200 | 4.70M | fxGetNextCharacter(parser); |
1201 | 4.70M | if (parser->character == '=') { |
1202 | 375 | parser->states[2].token = XS_TOKEN_SUBTRACT_ASSIGN; |
1203 | 375 | fxGetNextCharacter(parser); |
1204 | 375 | } |
1205 | 4.70M | else if (parser->character == '-') { |
1206 | 112k | parser->states[2].token = XS_TOKEN_DECREMENT; |
1207 | 112k | fxGetNextCharacter(parser); |
1208 | 112k | } |
1209 | 4.58M | else |
1210 | 4.58M | parser->states[2].token = XS_TOKEN_SUBTRACT; |
1211 | 4.70M | break; |
1212 | 49.0k | case '*': |
1213 | 49.0k | fxGetNextCharacter(parser); |
1214 | 49.0k | if (parser->character == '=') { |
1215 | 552 | parser->states[2].token = XS_TOKEN_MULTIPLY_ASSIGN; |
1216 | 552 | fxGetNextCharacter(parser); |
1217 | 552 | } |
1218 | 48.5k | else if (parser->character == '*') { |
1219 | 2.71k | fxGetNextCharacter(parser); |
1220 | 2.71k | if (parser->character == '=') { |
1221 | 6 | parser->states[2].token = XS_TOKEN_EXPONENTIATION_ASSIGN; |
1222 | 6 | fxGetNextCharacter(parser); |
1223 | 6 | } |
1224 | 2.70k | else |
1225 | 2.70k | parser->states[2].token = XS_TOKEN_EXPONENTIATION; |
1226 | 2.71k | } |
1227 | 45.7k | else |
1228 | 45.7k | parser->states[2].token = XS_TOKEN_MULTIPLY; |
1229 | 49.0k | break; |
1230 | 561k | case '/': |
1231 | 561k | fxGetNextCharacter(parser); |
1232 | 561k | if (parser->character == '*') { |
1233 | 27.6k | fxGetNextCharacter(parser); |
1234 | 5.70M | for (;;) { |
1235 | 5.70M | if (parser->character == (txU4)C_EOF) { |
1236 | 4.31k | fxReportParserError(parser, parser->states[2].line, "end of file in comment"); |
1237 | 4.31k | break; |
1238 | 4.31k | } |
1239 | 5.70M | else if ((parser->character == 10) || (parser->character == 0x2028) || (parser->character == 0x2029)) { |
1240 | 95.9k | parser->states[2].line++; |
1241 | 95.9k | fxGetNextCharacter(parser); |
1242 | 95.9k | parser->states[2].crlf = 1; |
1243 | 95.9k | } |
1244 | 5.60M | else if (parser->character == 13) { |
1245 | 16.0k | parser->states[2].line++; |
1246 | 16.0k | fxGetNextCharacter(parser); |
1247 | 16.0k | if (parser->character == 10) |
1248 | 4.43k | fxGetNextCharacter(parser); |
1249 | 16.0k | parser->states[2].crlf = 1; |
1250 | 16.0k | } |
1251 | 5.58M | else if (parser->character == '*') { |
1252 | 34.4k | fxGetNextCharacter(parser); |
1253 | 34.4k | if (parser->character == '/') { |
1254 | 23.3k | fxGetNextCharacter(parser); |
1255 | 23.3k | break; |
1256 | 23.3k | } |
1257 | 34.4k | } |
1258 | 5.55M | else |
1259 | 5.55M | fxGetNextCharacter(parser); |
1260 | 5.70M | } |
1261 | 27.6k | } |
1262 | 534k | else if (parser->character == '/') { |
1263 | 398k | fxGetNextCharacter(parser); |
1264 | 398k | p = parser->buffer; |
1265 | 398k | q = p + parser->bufferSize - 1; |
1266 | 29.9M | while ((parser->character != (txU4)C_EOF) && (parser->character != 10) && (parser->character != 13) && (parser->character != 0x2028) && (parser->character != 0x2029)) { |
1267 | 29.5M | if (p < q) |
1268 | 29.4M | *p++ = (char)parser->character; |
1269 | 29.5M | fxGetNextCharacter(parser); |
1270 | 29.5M | } |
1271 | 398k | *p = 0; |
1272 | 398k | p = parser->buffer; |
1273 | 398k | if ((*p == '#') || (*p == '@')) { |
1274 | 33.5k | if (!c_strncmp(p, "@line ", 6)) { |
1275 | 13.3k | p += 6; |
1276 | 13.3k | t = 0; |
1277 | 13.3k | c = *p++; |
1278 | 114k | while (('0' <= c) && (c <= '9')) { |
1279 | 100k | t = (t * 10) + (c - '0'); |
1280 | 100k | c = *p++; |
1281 | 100k | } |
1282 | 13.3k | if (!t) goto bail; |
1283 | 11.5k | if (c == ' ') { |
1284 | 3.62k | c = *p++; |
1285 | 3.62k | if (c != '"') goto bail; |
1286 | 2.33k | q = p; |
1287 | 2.33k | c = *q++; |
1288 | 53.4k | while ((c != 0) && (c != 10) && (c != 13) && (c != '"')) |
1289 | 51.1k | c = *q++; |
1290 | 2.33k | if (c != '"') goto bail; |
1291 | 427 | *(--q) = 0; |
1292 | 427 | parser->path = fxNewParserSymbol(parser, p); |
1293 | 427 | } |
1294 | 8.36k | parser->states[2].line = t - 1; |
1295 | 8.36k | } |
1296 | 20.2k | else if (!c_strncmp(p, "# sourceMappingURL=", 19) || !c_strncmp(p, "@ sourceMappingURL=", 19)) { |
1297 | 823 | p += 19; |
1298 | 823 | q = p; |
1299 | 28.2k | while (((c = *q)) && (c != 10) && (c != 13)) |
1300 | 27.4k | q++; |
1301 | 823 | *q = 0; |
1302 | 823 | parser->name = fxNewParserString(parser, p, mxPtrDiff(q - p)); |
1303 | 823 | } |
1304 | 19.4k | else if (!c_strncmp(p, "# sourceURL=", 12) || !c_strncmp(p, "@ sourceURL=", 12)) { |
1305 | 799 | p += 12; |
1306 | 799 | q = p; |
1307 | 139k | while (((c = *q)) && (c != 10) && (c != 13)) |
1308 | 138k | q++; |
1309 | 799 | *q = 0; |
1310 | 799 | parser->source = fxNewParserSymbol(parser, p); |
1311 | 799 | } |
1312 | 33.5k | } |
1313 | 398k | bail: |
1314 | 398k | ; |
1315 | 398k | } |
1316 | 135k | else if (parser->character == '=') { |
1317 | 1.44k | parser->states[2].token = XS_TOKEN_DIVIDE_ASSIGN; |
1318 | 1.44k | fxGetNextCharacter(parser); |
1319 | 1.44k | } |
1320 | 133k | else |
1321 | 133k | parser->states[2].token = XS_TOKEN_DIVIDE; |
1322 | 561k | break; |
1323 | 561k | case '%': |
1324 | 10.1k | fxGetNextCharacter(parser); |
1325 | 10.1k | if (parser->character == '=') { |
1326 | 1.23k | parser->states[2].token = XS_TOKEN_MODULO_ASSIGN; |
1327 | 1.23k | fxGetNextCharacter(parser); |
1328 | 1.23k | } |
1329 | 8.93k | else |
1330 | 8.93k | parser->states[2].token = XS_TOKEN_MODULO; |
1331 | 10.1k | break; |
1332 | | |
1333 | 170k | case '"': |
1334 | 281k | case '\'': |
1335 | 281k | c = parser->character; |
1336 | 281k | fxGetNextCharacter(parser); |
1337 | 281k | fxGetNextString(parser, c); |
1338 | 281k | parser->states[2].token = XS_TOKEN_STRING; |
1339 | 281k | fxGetNextCharacter(parser); |
1340 | 281k | break; |
1341 | | |
1342 | 410k | case '`': |
1343 | 410k | fxGetNextCharacter(parser); |
1344 | 410k | fxGetNextString(parser, '`'); |
1345 | 410k | if (parser->character == '{') |
1346 | 914 | parser->states[2].token = XS_TOKEN_TEMPLATE_HEAD; |
1347 | 409k | else |
1348 | 409k | parser->states[2].token = XS_TOKEN_TEMPLATE; |
1349 | 410k | fxGetNextCharacter(parser); |
1350 | 410k | break; |
1351 | | |
1352 | 2.89k | case '@': |
1353 | 2.89k | if (parser->flags & mxCFlag) |
1354 | 0 | parser->states[2].token = XS_TOKEN_HOST; |
1355 | 2.89k | else |
1356 | 2.89k | fxReportParserError(parser, parser->states[2].line, "invalid character @"); |
1357 | 2.89k | fxGetNextCharacter(parser); |
1358 | 2.89k | break; |
1359 | | |
1360 | 3.51M | default: |
1361 | 3.51M | p = parser->buffer; |
1362 | 3.51M | q = p + parser->bufferSize - 1; |
1363 | 3.51M | if (parser->character == '#') { |
1364 | 24.3k | *p++ = '#'; |
1365 | 24.3k | fxGetNextCharacter(parser); |
1366 | 24.3k | } |
1367 | 3.51M | if (fxIsIdentifierFirst(parser->character)) { |
1368 | 3.35M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1369 | 3.35M | fxGetNextCharacter(parser); |
1370 | 3.35M | } |
1371 | 155k | else if (parser->character == '\\') { |
1372 | 3.20k | parser->states[2].escaped = 1; |
1373 | 3.20k | t = 0; |
1374 | 3.20k | if (fxGetNextIdentiferX(parser, &t) && fxIsIdentifierFirst(t)) |
1375 | 957 | p = fxUTF8Buffer(parser, t, p, q); |
1376 | 2.24k | else |
1377 | 2.24k | p = C_NULL; |
1378 | 3.20k | } |
1379 | 152k | else |
1380 | 152k | p = C_NULL; |
1381 | 3.51M | if (p) { |
1382 | 15.9M | for (;;) { |
1383 | 15.9M | if (p == q) { |
1384 | 1 | fxReportMemoryError(parser, parser->states[2].line, "identifier overflow"); |
1385 | 1 | } |
1386 | 15.9M | if (fxIsIdentifierNext(parser->character)) { |
1387 | 12.5M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1388 | 12.5M | fxGetNextCharacter(parser); |
1389 | 12.5M | } |
1390 | 3.35M | else if (parser->character == '\\') { |
1391 | 6.61k | parser->states[2].escaped = 1; |
1392 | 6.61k | t = 0; |
1393 | 6.61k | if (fxGetNextIdentiferX(parser, &t) && fxIsIdentifierNext(t)) |
1394 | 300 | p = fxUTF8Buffer(parser, t, p, q); |
1395 | 6.31k | else { |
1396 | 6.31k | p = C_NULL; |
1397 | 6.31k | break; |
1398 | 6.31k | } |
1399 | 6.61k | } |
1400 | 3.35M | else { |
1401 | 3.35M | *p = 0; |
1402 | 3.35M | if (parser->buffer[0] == '#') { |
1403 | 16.7k | parser->states[2].symbol = fxNewParserSymbol(parser, parser->buffer); |
1404 | 16.7k | parser->states[2].token = XS_TOKEN_PRIVATE_IDENTIFIER; |
1405 | 16.7k | } |
1406 | 3.33M | else { |
1407 | 3.33M | fxGetNextKeyword(parser); |
1408 | 3.33M | } |
1409 | 3.35M | break; |
1410 | 3.35M | } |
1411 | 15.9M | } |
1412 | 3.35M | } |
1413 | 3.51M | if (!p) { |
1414 | 161k | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1415 | 161k | fxGetNextCharacter(parser); |
1416 | 161k | } |
1417 | 3.51M | break; |
1418 | 25.3M | } |
1419 | 25.3M | } |
1420 | 19.7M | } |
1421 | | |
1422 | | void fxGetNextTokenTemplate(txParser* parser) |
1423 | 4.83k | { |
1424 | 4.83k | parser->states[2].crlf = 0; |
1425 | 4.83k | parser->states[2].escaped = 0; |
1426 | 4.83k | parser->states[2].integer = 0; |
1427 | 4.83k | parser->states[2].modifierLength = 0; |
1428 | 4.83k | parser->states[2].modifier = parser->emptyString; |
1429 | 4.83k | parser->states[2].number = 0; |
1430 | 4.83k | parser->states[2].rawLength = 0; |
1431 | 4.83k | parser->states[2].raw = parser->emptyString; |
1432 | 4.83k | parser->states[2].stringLength = 0; |
1433 | 4.83k | parser->states[2].string = parser->emptyString; |
1434 | 4.83k | parser->states[2].symbol = C_NULL; |
1435 | 4.83k | parser->states[2].token = XS_NO_TOKEN; |
1436 | 4.83k | fxGetNextString(parser, '`'); |
1437 | 4.83k | if (parser->character == '{') |
1438 | 3.93k | parser->states[2].token = XS_TOKEN_TEMPLATE_MIDDLE; |
1439 | 897 | else |
1440 | 897 | parser->states[2].token = XS_TOKEN_TEMPLATE_TAIL; |
1441 | 4.83k | fxGetNextCharacter(parser); |
1442 | 4.83k | parser->states[0] = parser->states[2]; |
1443 | 4.83k | parser->ahead = 0; |
1444 | 4.83k | } |
1445 | | |
1446 | | void fxGetNextTokenJSON(txParser* parser) |
1447 | 0 | { |
1448 | 0 | int c; |
1449 | 0 | txString p; |
1450 | 0 | txString q; |
1451 | |
|
1452 | 0 | parser->states[0] = parser->states[2]; |
1453 | | |
1454 | 0 | parser->states[2].crlf = 0; |
1455 | 0 | parser->states[2].escaped = 0; |
1456 | 0 | parser->states[2].integer = 0; |
1457 | 0 | parser->states[2].modifierLength = 0; |
1458 | 0 | parser->states[2].modifier = parser->emptyString; |
1459 | 0 | parser->states[2].number = 0; |
1460 | 0 | parser->states[2].rawLength = 0; |
1461 | 0 | parser->states[2].raw = parser->emptyString; |
1462 | 0 | parser->states[2].stringLength = 0; |
1463 | 0 | parser->states[2].string = parser->emptyString; |
1464 | 0 | parser->states[2].symbol = C_NULL; |
1465 | 0 | parser->states[2].token = XS_NO_TOKEN; |
1466 | | |
1467 | 0 | while (parser->states[2].token == XS_NO_TOKEN) { |
1468 | 0 | switch (parser->character) { |
1469 | 0 | case C_EOF: |
1470 | 0 | parser->states[2].token = XS_TOKEN_EOF; |
1471 | 0 | break; |
1472 | 0 | case 10: |
1473 | 0 | parser->states[2].line++; |
1474 | 0 | fxGetNextCharacter(parser); |
1475 | 0 | parser->states[2].crlf = 1; |
1476 | 0 | break; |
1477 | 0 | case 13: |
1478 | 0 | parser->states[2].line++; |
1479 | 0 | fxGetNextCharacter(parser); |
1480 | 0 | if (parser->character == 10) |
1481 | 0 | fxGetNextCharacter(parser); |
1482 | 0 | parser->states[2].crlf = 1; |
1483 | 0 | break; |
1484 | | |
1485 | 0 | case '\t': |
1486 | 0 | case ' ': |
1487 | 0 | fxGetNextCharacter(parser); |
1488 | 0 | break; |
1489 | | |
1490 | 0 | case '0': |
1491 | 0 | fxGetNextCharacter(parser); |
1492 | 0 | c = parser->character; |
1493 | 0 | if (c == '.') { |
1494 | 0 | fxGetNextCharacter(parser); |
1495 | 0 | c = parser->character; |
1496 | 0 | if ((('0' <= c) && (c <= '9')) || (c == 'e') || (c == 'E')) |
1497 | 0 | fxGetNextNumberE(parser, 1); |
1498 | 0 | else { |
1499 | 0 | parser->states[2].number = 0; |
1500 | 0 | parser->states[2].token = XS_TOKEN_NUMBER; |
1501 | 0 | } |
1502 | 0 | } |
1503 | 0 | else if ((c == 'b') || (c == 'B')) { |
1504 | 0 | fxGetNextNumberB(parser); |
1505 | 0 | } |
1506 | 0 | else if ((c == 'e') || (c == 'E')) { |
1507 | 0 | fxGetNextNumberE(parser, 0); |
1508 | 0 | } |
1509 | 0 | else if ((c == 'o') || (c == 'O')) { |
1510 | 0 | fxGetNextNumberO(parser, '0', 0); |
1511 | 0 | } |
1512 | 0 | else if ((c == 'x') || (c == 'X')) { |
1513 | 0 | fxGetNextNumberX(parser); |
1514 | 0 | } |
1515 | 0 | else { |
1516 | 0 | parser->states[2].integer = 0; |
1517 | 0 | parser->states[2].token = XS_TOKEN_INTEGER; |
1518 | 0 | } |
1519 | 0 | break; |
1520 | 0 | case '1': |
1521 | 0 | case '2': |
1522 | 0 | case '3': |
1523 | 0 | case '4': |
1524 | 0 | case '5': |
1525 | 0 | case '6': |
1526 | 0 | case '7': |
1527 | 0 | case '8': |
1528 | 0 | case '9': |
1529 | 0 | fxGetNextNumberE(parser, 0); |
1530 | 0 | break; |
1531 | 0 | case '-': |
1532 | 0 | fxGetNextCharacter(parser); |
1533 | 0 | fxGetNextNumberE(parser, 0); |
1534 | 0 | if (parser->states[2].token == XS_TOKEN_INTEGER) |
1535 | 0 | parser->states[2].integer = 0 - parser->states[2].integer; |
1536 | 0 | else |
1537 | 0 | parser->states[2].number = 0 - parser->states[2].number; |
1538 | 0 | break; |
1539 | 0 | case ',': |
1540 | 0 | parser->states[2].token = XS_TOKEN_COMMA; |
1541 | 0 | fxGetNextCharacter(parser); |
1542 | 0 | break; |
1543 | 0 | case ':': |
1544 | 0 | parser->states[2].token = XS_TOKEN_COLON; |
1545 | 0 | fxGetNextCharacter(parser); |
1546 | 0 | break; |
1547 | 0 | case '[': |
1548 | 0 | parser->states[2].token = XS_TOKEN_LEFT_BRACKET; |
1549 | 0 | fxGetNextCharacter(parser); |
1550 | 0 | break; |
1551 | 0 | case ']': |
1552 | 0 | parser->states[2].token = XS_TOKEN_RIGHT_BRACKET; |
1553 | 0 | fxGetNextCharacter(parser); |
1554 | 0 | break; |
1555 | 0 | case '{': |
1556 | 0 | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1557 | 0 | fxGetNextCharacter(parser); |
1558 | 0 | break; |
1559 | 0 | case '}': |
1560 | 0 | parser->states[2].token = XS_TOKEN_RIGHT_BRACE; |
1561 | 0 | fxGetNextCharacter(parser); |
1562 | 0 | break; |
1563 | 0 | case '"': |
1564 | 0 | fxGetNextCharacter(parser); |
1565 | 0 | fxGetNextString(parser, '"'); |
1566 | 0 | parser->states[2].token = XS_TOKEN_STRING; |
1567 | 0 | fxGetNextCharacter(parser); |
1568 | 0 | break; |
1569 | 0 | default: |
1570 | 0 | if (fxIsIdentifierFirst((char)parser->character)) { |
1571 | 0 | p = parser->buffer; |
1572 | 0 | q = p + parser->bufferSize - 1; |
1573 | 0 | for (;;) { |
1574 | 0 | if (p == q) { |
1575 | 0 | fxReportMemoryError(parser, parser->states[2].line, "identifier overflow"); |
1576 | 0 | } |
1577 | 0 | *p++ = (char)parser->character; |
1578 | 0 | fxGetNextCharacter(parser); |
1579 | 0 | if (!fxIsIdentifierNext((char)parser->character)) |
1580 | 0 | break; |
1581 | 0 | } |
1582 | 0 | *p = 0; |
1583 | 0 | if (!c_strcmp("false", parser->buffer)) |
1584 | 0 | parser->states[2].token = XS_TOKEN_FALSE; |
1585 | 0 | else if (!c_strcmp("null", parser->buffer)) |
1586 | 0 | parser->states[2].token = XS_TOKEN_NULL; |
1587 | 0 | else if (!c_strcmp("true", parser->buffer)) |
1588 | 0 | parser->states[2].token = XS_TOKEN_TRUE; |
1589 | 0 | else { |
1590 | 0 | parser->states[2].symbol = fxNewParserSymbol(parser, parser->buffer); |
1591 | 0 | parser->states[2].token = XS_TOKEN_IDENTIFIER; |
1592 | 0 | } |
1593 | 0 | } |
1594 | 0 | else { |
1595 | 0 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1596 | 0 | fxGetNextCharacter(parser); |
1597 | 0 | } |
1598 | 0 | break; |
1599 | 0 | } |
1600 | 0 | } |
1601 | 0 | } |
1602 | | |
1603 | | typedef struct { |
1604 | | char* name; |
1605 | | int value; |
1606 | | } txEntity; |
1607 | | |
1608 | | static int fxCompareEntities(const void *name, const void *entity); |
1609 | | |
1610 | 48.6k | #define XS_ENTITIES_COUNT 253 |
1611 | | static const txEntity ICACHE_RODATA_ATTR gxEntities[XS_ENTITIES_COUNT] = { |
1612 | | { "AElig", 0x00C6 }, { "Aacute", 0x00C1 }, { "Acirc", 0x00C2 }, { "Agrave", 0x00C0 }, { "Alpha", 0x0391 }, { "Aring", 0x00C5 }, { "Atilde", 0x00C3 }, { "Auml", 0x00C4 }, |
1613 | | { "Beta", 0x0392 }, { "Ccedil", 0x00C7 }, { "Chi", 0x03A7 }, { "Dagger", 0x2021 }, { "Delta", 0x0394 }, { "ETH", 0x00D0 }, { "Eacute", 0x00C9 }, { "Ecirc", 0x00CA }, |
1614 | | { "Egrave", 0x00C8 }, { "Epsilon", 0x0395 }, { "Eta", 0x0397 }, { "Euml", 0x00CB }, { "Gamma", 0x0393 }, { "Iacute", 0x00CD }, { "Icirc", 0x00CE }, { "Igrave", 0x00CC }, |
1615 | | { "Iota", 0x0399 }, { "Iuml", 0x00CF }, { "Kappa", 0x039A }, { "Lambda", 0x039B }, { "Mu", 0x039C }, { "Ntilde", 0x00D1 }, { "Nu", 0x039D }, { "OElig", 0x0152 }, |
1616 | | { "Oacute", 0x00D3 }, { "Ocirc", 0x00D4 }, { "Ograve", 0x00D2 }, { "Omega", 0x03A9 }, { "Omicron", 0x039F }, { "Oslash", 0x00D8 }, { "Otilde", 0x00D5 }, { "Ouml", 0x00D6 }, |
1617 | | { "Phi", 0x03A6 }, { "Pi", 0x03A0 }, { "Prime", 0x2033 }, { "Psi", 0x03A8 }, { "Rho", 0x03A1 }, { "Scaron", 0x0160 }, { "Sigma", 0x03A3 }, { "THORN", 0x00DE }, |
1618 | | { "Tau", 0x03A4 }, { "Theta", 0x0398 }, { "Uacute", 0x00DA }, { "Ucirc", 0x00DB }, { "Ugrave", 0x00D9 }, { "Upsilon", 0x03A5 }, { "Uuml", 0x00DC }, { "Xi", 0x039E }, |
1619 | | { "Yacute", 0x00DD }, { "Yuml", 0x0178 }, { "Zeta", 0x0396 }, { "aacute", 0x00E1 }, { "acirc", 0x00E2 }, { "acute", 0x00B4 }, { "aelig", 0x00E6 }, { "agrave", 0x00E0 }, |
1620 | | { "alefsym", 0x2135 }, { "alpha", 0x03B1 }, { "amp", 0x0026 }, { "and", 0x2227 }, { "ang", 0x2220 }, { "apos", 0x0027 }, { "aring", 0x00E5 }, { "asymp", 0x2248 }, |
1621 | | { "atilde", 0x00E3 }, { "auml", 0x00E4 }, { "bdquo", 0x201E }, { "beta", 0x03B2 }, { "brvbar", 0x00A6 }, { "bull", 0x2022 }, { "cap", 0x2229 }, { "ccedil", 0x00E7 }, |
1622 | | { "cedil", 0x00B8 }, { "cent", 0x00A2 }, { "chi", 0x03C7 }, { "circ", 0x02C6 }, { "clubs", 0x2663 }, { "cong", 0x2245 }, { "copy", 0x00A9 }, { "crarr", 0x21B5 }, |
1623 | | { "cup", 0x222A }, { "curren", 0x00A4 }, { "dArr", 0x21D3 }, { "dagger", 0x2020 }, { "darr", 0x2193 }, { "deg", 0x00B0 }, { "delta", 0x03B4 }, { "diams", 0x2666 }, |
1624 | | { "divide", 0x00F7 }, { "eacute", 0x00E9 }, { "ecirc", 0x00EA }, { "egrave", 0x00E8 }, { "empty", 0x2205 }, { "emsp", 0x2003 }, { "ensp", 0x2002 }, { "epsilon", 0x03B5 }, |
1625 | | { "equiv", 0x2261 }, { "eta", 0x03B7 }, { "eth", 0x00F0 }, { "euml", 0x00EB }, { "euro", 0x20AC }, { "exist", 0x2203 }, { "fnof", 0x0192 }, { "forall", 0x2200 }, |
1626 | | { "frac12", 0x00BD }, { "frac14", 0x00BC }, { "frac34", 0x00BE }, { "frasl", 0x2044 }, { "gamma", 0x03B3 }, { "ge", 0x2265 }, { "gt", 0x003E }, { "hArr", 0x21D4 }, |
1627 | | { "harr", 0x2194 }, { "hearts", 0x2665 }, { "hellip", 0x2026 }, { "iacute", 0x00ED }, { "icirc", 0x00EE }, { "iexcl", 0x00A1 }, { "igrave", 0x00EC }, { "image", 0x2111 }, |
1628 | | { "infin", 0x221E }, { "int", 0x222B }, { "iota", 0x03B9 }, { "iquest", 0x00BF }, { "isin", 0x2208 }, { "iuml", 0x00EF }, { "kappa", 0x03BA }, { "lArr", 0x21D0 }, |
1629 | | { "lambda", 0x03BB }, { "lang", 0x2329 }, { "laquo", 0x00AB }, { "larr", 0x2190 }, { "lceil", 0x2308 }, { "ldquo", 0x201C }, { "le", 0x2264 }, { "lfloor", 0x230A }, |
1630 | | { "lowast", 0x2217 }, { "loz", 0x25CA }, { "lrm", 0x200E }, { "lsaquo", 0x2039 }, { "lsquo", 0x2018 }, { "lt", 0x003C }, { "macr", 0x00AF }, { "mdash", 0x2014 }, |
1631 | | { "micro", 0x00B5 }, { "middot", 0x00B7 }, { "minus", 0x2212 }, { "mu", 0x03BC }, { "nabla", 0x2207 }, { "nbsp", 0x00A0 }, { "ndash", 0x2013 }, { "ne", 0x2260 }, |
1632 | | { "ni", 0x220B }, { "not", 0x00AC }, { "notin", 0x2209 }, { "nsub", 0x2284 }, { "ntilde", 0x00F1 }, { "nu", 0x03BD }, { "oacute", 0x00F3 }, { "ocirc", 0x00F4 }, |
1633 | | { "oelig", 0x0153 }, { "ograve", 0x00F2 }, { "oline", 0x203E }, { "omega", 0x03C9 }, { "omicron", 0x03BF }, { "oplus", 0x2295 }, { "or", 0x2228 }, { "ordf", 0x00AA }, |
1634 | | { "ordm", 0x00BA }, { "oslash", 0x00F8 }, { "otilde", 0x00F5 }, { "otimes", 0x2297 }, { "ouml", 0x00F6 }, { "para", 0x00B6 }, { "part", 0x2202 }, { "permil", 0x2030 }, |
1635 | | { "perp", 0x22A5 }, { "phi", 0x03C6 }, { "pi", 0x03C0 }, { "piv", 0x03D6 }, { "plusmn", 0x00B1 }, { "pound", 0x00A3 }, { "prime", 0x2032 }, { "prod", 0x220F }, |
1636 | | { "prop", 0x221D }, { "psi", 0x03C8 }, { "quot", 0x0022 }, { "rArr", 0x21D2 }, { "radic", 0x221A }, { "rang", 0x232A }, { "raquo", 0x00BB }, { "rarr", 0x2192 }, |
1637 | | { "rceil", 0x2309 }, { "rdquo", 0x201D }, { "real", 0x211C }, { "reg", 0x00AE }, { "rfloor", 0x230B }, { "rho", 0x03C1 }, { "rlm", 0x200F }, { "rsaquo", 0x203A }, |
1638 | | { "rsquo", 0x2019 }, { "sbquo", 0x201A }, { "scaron", 0x0161 }, { "sdot", 0x22C5 }, { "sect", 0x00A7 }, { "shy", 0x00AD }, { "sigma", 0x03C3 }, { "sigmaf", 0x03C2 }, |
1639 | | { "sim", 0x223C }, { "spades", 0x2660 }, { "sub", 0x2282 }, { "sube", 0x2286 }, { "sum", 0x2211 }, { "sup", 0x2283 }, { "sup1", 0x00B9 }, { "sup2", 0x00B2 }, |
1640 | | { "sup3", 0x00B3 }, { "supe", 0x2287 }, { "szlig", 0x00DF }, { "tau", 0x03C4 }, { "there4", 0x2234 }, { "theta", 0x03B8 }, { "thetasym", 0x03D1 }, { "thinsp", 0x2009 }, |
1641 | | { "thorn", 0x00FE }, { "tilde", 0x02DC }, { "times", 0x00D7 }, { "trade", 0x2122 }, { "uArr", 0x21D1 }, { "uacute", 0x00FA }, { "uarr", 0x2191 }, { "ucirc", 0x00FB }, |
1642 | | { "ugrave", 0x00F9 }, { "uml", 0x00A8 }, { "upsih", 0x03D2 }, { "upsilon", 0x03C5 }, { "uuml", 0x00FC }, { "weierp", 0x2118 }, { "xi", 0x03BE }, { "yacute", 0x00FD }, |
1643 | | { "yen", 0x00A5 }, { "yuml", 0x00FF }, { "zeta", 0x03B6 }, { "zwj", 0x200D }, { "zwnj", 0x200C }, |
1644 | | }; |
1645 | | |
1646 | | int fxCompareEntities(const void *name, const void *entity) |
1647 | 389k | { |
1648 | 389k | return c_strcmp((char*)name, ((txEntity*)entity)->name); |
1649 | 389k | } |
1650 | | |
1651 | | txString fxGetNextEntity(txParser* parser, txString p, txString q) |
1652 | 51.9k | { |
1653 | 51.9k | txString r = p; |
1654 | 51.9k | txU4 t = 0; |
1655 | 51.9k | if (p < q) *p++ = '&'; |
1656 | 51.9k | fxGetNextCharacter(parser); |
1657 | 51.9k | if (parser->character == '#') { |
1658 | 3.20k | if (p < q) *p++ = '#'; |
1659 | 3.20k | fxGetNextCharacter(parser); |
1660 | 3.20k | if (parser->character == 'x') { |
1661 | 2.35k | if (p < q) *p++ = 'x'; |
1662 | 2.35k | fxGetNextCharacter(parser); |
1663 | 11.7k | while (fxGetNextStringX(parser->character, &t)) { |
1664 | 9.35k | if (p < q) *p++ = parser->character; |
1665 | 9.35k | fxGetNextCharacter(parser); |
1666 | 9.35k | } |
1667 | 2.35k | } |
1668 | 850 | else { |
1669 | 1.37k | while (fxGetNextStringD(parser->character, &t)) { |
1670 | 525 | if (p < q) *p++ = parser->character; |
1671 | 525 | fxGetNextCharacter(parser); |
1672 | 525 | } |
1673 | 850 | } |
1674 | 3.20k | } |
1675 | 48.7k | else { |
1676 | 48.7k | txEntity* entity = C_NULL; |
1677 | 48.7k | int c = parser->character; |
1678 | 65.0k | while ((p < q) && ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z')))) { |
1679 | 16.2k | if (p < q) *p++ = c; |
1680 | 16.2k | fxGetNextCharacter(parser); |
1681 | 16.2k | c = parser->character; |
1682 | 16.2k | } |
1683 | 48.7k | *p = 0; |
1684 | 48.7k | if (r < q) |
1685 | 48.6k | entity = (txEntity*)c_bsearch(r + 1, gxEntities, XS_ENTITIES_COUNT, sizeof(txEntity), fxCompareEntities); |
1686 | 48.7k | t = entity ? entity->value : 0; |
1687 | 48.7k | } |
1688 | 51.9k | if (parser->character == ';') { |
1689 | 2.20k | if (p < q) *p++ = ';'; |
1690 | 2.20k | fxGetNextCharacter(parser); |
1691 | 2.20k | if (t) |
1692 | 1.92k | p = fxUTF8Buffer(parser, t, r, q); |
1693 | 2.20k | } |
1694 | 51.9k | return p; |
1695 | 51.9k | } |
1696 | | |
1697 | | void fxGetNextTokenJSXAttribute(txParser* parser) |
1698 | 3.00k | { |
1699 | 3.00k | txString p = parser->buffer; |
1700 | 3.00k | txString q = p + parser->bufferSize - 1; |
1701 | 3.00k | txU4 quote = 0; |
1702 | 3.00k | parser->states[2].crlf = 0; |
1703 | 3.00k | parser->states[2].escaped = 0; |
1704 | 3.00k | parser->states[2].integer = 0; |
1705 | 3.00k | parser->states[2].modifierLength = 0; |
1706 | 3.00k | parser->states[2].modifier = parser->emptyString; |
1707 | 3.00k | parser->states[2].number = 0; |
1708 | 3.00k | parser->states[2].rawLength = 0; |
1709 | 3.00k | parser->states[2].raw = parser->emptyString; |
1710 | 3.00k | parser->states[2].stringLength = 0; |
1711 | 3.00k | parser->states[2].string = parser->emptyString; |
1712 | 3.00k | parser->states[2].symbol = C_NULL; |
1713 | 3.00k | parser->states[2].token = XS_NO_TOKEN; |
1714 | 1.91M | while (parser->states[2].token == XS_NO_TOKEN) { |
1715 | 1.90M | switch (parser->character) { |
1716 | 1.04k | case C_EOF: |
1717 | 1.04k | parser->states[2].token = XS_TOKEN_EOF; |
1718 | 1.04k | break; |
1719 | 30.9k | case 10: |
1720 | 31.0k | case 0x2028: // <LS> |
1721 | 31.4k | case 0x2029: // <PS> |
1722 | 31.4k | parser->states[2].line++; |
1723 | 31.4k | if (quote) |
1724 | 20.0k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1725 | 31.4k | fxGetNextCharacter(parser); |
1726 | 31.4k | parser->states[2].crlf = 1; |
1727 | 31.4k | break; |
1728 | 105k | case 13: |
1729 | 105k | parser->states[2].line++; |
1730 | 105k | if (quote) |
1731 | 105k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1732 | 105k | fxGetNextCharacter(parser); |
1733 | 105k | if (parser->character == 10) { |
1734 | 2.58k | if (quote) |
1735 | 2.47k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1736 | 2.58k | fxGetNextCharacter(parser); |
1737 | 2.58k | } |
1738 | 105k | parser->states[2].crlf = 1; |
1739 | 105k | break; |
1740 | 2.06k | case '\t': |
1741 | 2.66k | case 11: |
1742 | 4.86k | case 12: |
1743 | 56.2k | case ' ': |
1744 | 56.2k | case 0x00A0: |
1745 | 57.4k | case 0x1680: |
1746 | 57.8k | case 0x2000: |
1747 | 57.9k | case 0x2001: |
1748 | 57.9k | case 0x2002: |
1749 | 59.1k | case 0x2003: |
1750 | 59.1k | case 0x2004: |
1751 | 59.3k | case 0x2005: |
1752 | 59.5k | case 0x2006: |
1753 | 59.6k | case 0x2007: |
1754 | 59.6k | case 0x2008: |
1755 | 59.6k | case 0x2009: |
1756 | 59.8k | case 0x200A: |
1757 | 59.9k | case 0x202F: |
1758 | 59.9k | case 0x205F: |
1759 | 59.9k | case 0x3000: |
1760 | 60.0k | case 0xFEFF: |
1761 | 60.0k | if (quote) |
1762 | 59.5k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1763 | 60.0k | fxGetNextCharacter(parser); |
1764 | 60.0k | break; |
1765 | | |
1766 | 16.5k | case '{': |
1767 | 16.5k | if (quote) |
1768 | 16.5k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1769 | 15 | else |
1770 | 15 | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1771 | 16.5k | fxGetNextCharacter(parser); |
1772 | 16.5k | break; |
1773 | | |
1774 | 5.65k | case '"': |
1775 | 77.9k | case '\'': |
1776 | 77.9k | if (quote) { |
1777 | 75.4k | if (quote == parser->character) { |
1778 | 1.52k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
1779 | 1.52k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
1780 | 1.52k | parser->states[2].token = XS_TOKEN_STRING; |
1781 | 1.52k | } |
1782 | 73.8k | else |
1783 | 73.8k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1784 | 75.4k | } |
1785 | 2.59k | else |
1786 | 2.59k | quote = parser->character; |
1787 | 77.9k | fxGetNextCharacter(parser); |
1788 | 77.9k | break; |
1789 | | |
1790 | 50.1k | case '&': |
1791 | 50.1k | if (quote) |
1792 | 50.1k | p = fxGetNextEntity(parser, p, q); |
1793 | 1 | else { |
1794 | 1 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1795 | 1 | fxGetNextCharacter(parser); |
1796 | 1 | } |
1797 | 50.1k | break; |
1798 | | |
1799 | 1.56M | default: |
1800 | 1.56M | if (quote) |
1801 | 1.56M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1802 | 391 | else |
1803 | 391 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1804 | 1.56M | fxGetNextCharacter(parser); |
1805 | 1.56M | break; |
1806 | 1.90M | } |
1807 | 1.90M | } |
1808 | 2.59k | parser->states[0] = parser->states[2]; |
1809 | 2.59k | parser->ahead = 0; |
1810 | 2.59k | } |
1811 | | |
1812 | | void fxGetNextTokenJSXChild(txParser* parser) |
1813 | 33.4k | { |
1814 | 33.4k | txString p = parser->buffer; |
1815 | 33.4k | txString q = p + parser->bufferSize - 1; |
1816 | 33.4k | txString s = C_NULL; |
1817 | 33.4k | char c; |
1818 | 33.4k | txString after = C_NULL; |
1819 | 33.4k | txString before = C_NULL; |
1820 | 33.4k | txString text = C_NULL; |
1821 | 33.4k | parser->states[2].crlf = 0; |
1822 | 33.4k | parser->states[2].escaped = 0; |
1823 | 33.4k | parser->states[2].integer = 0; |
1824 | 33.4k | parser->states[2].modifierLength = 0; |
1825 | 33.4k | parser->states[2].modifier = parser->emptyString; |
1826 | 33.4k | parser->states[2].number = 0; |
1827 | 33.4k | parser->states[2].rawLength = 0; |
1828 | 33.4k | parser->states[2].raw = parser->emptyString; |
1829 | 33.4k | parser->states[2].stringLength = 0; |
1830 | 33.4k | parser->states[2].string = parser->emptyString; |
1831 | 33.4k | parser->states[2].symbol = C_NULL; |
1832 | 33.4k | parser->states[2].token = XS_NO_TOKEN; |
1833 | 536k | while (parser->states[2].token == XS_NO_TOKEN) { |
1834 | 503k | switch (parser->character) { |
1835 | 639 | case C_EOF: |
1836 | 639 | parser->states[2].token = XS_TOKEN_EOF; |
1837 | 639 | break; |
1838 | 18.7k | case 10: |
1839 | 18.9k | case 0x2028: // <LS> |
1840 | 19.0k | case 0x2029: // <PS> |
1841 | 19.0k | parser->states[2].line++; |
1842 | 19.0k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1843 | 19.0k | fxGetNextCharacter(parser); |
1844 | 19.0k | parser->states[2].crlf = 1; |
1845 | 19.0k | break; |
1846 | 430 | case 13: |
1847 | 430 | parser->states[2].line++; |
1848 | 430 | p = fxUTF8Buffer(parser, parser->character, p, q); |
1849 | 430 | fxGetNextCharacter(parser); |
1850 | 430 | if (parser->character == 10) { |
1851 | 44 | p = fxUTF8Buffer(parser, parser->character, p, q); |
1852 | 44 | fxGetNextCharacter(parser); |
1853 | 44 | } |
1854 | 430 | parser->states[2].crlf = 1; |
1855 | 430 | break; |
1856 | | |
1857 | 28.1k | case '<': |
1858 | 28.1k | fxGetNextCharacter(parser); |
1859 | 28.1k | parser->states[2].token = XS_TOKEN_LESS; |
1860 | 28.1k | break; |
1861 | 538 | case '>': |
1862 | 538 | fxGetNextCharacter(parser); |
1863 | 538 | parser->states[2].token = XS_TOKEN_MORE; |
1864 | 538 | break; |
1865 | 1.56k | case '{': |
1866 | 1.56k | fxGetNextCharacter(parser); |
1867 | 1.56k | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1868 | 1.56k | break; |
1869 | 2.61k | case '}': |
1870 | 2.61k | fxGetNextCharacter(parser); |
1871 | 2.61k | parser->states[2].token = XS_TOKEN_RIGHT_BRACE; |
1872 | 2.61k | break; |
1873 | 1.83k | case '&': |
1874 | 1.83k | p = fxGetNextEntity(parser, p, q); |
1875 | 1.83k | break; |
1876 | 448k | default: |
1877 | 448k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1878 | 448k | fxGetNextCharacter(parser); |
1879 | 448k | break; |
1880 | 503k | } |
1881 | 503k | } |
1882 | 33.4k | parser->states[2].rawLength = mxPtrDiff(p - parser->buffer); |
1883 | 33.4k | parser->states[2].raw = fxNewParserString(parser, parser->buffer, parser->states[2].rawLength); |
1884 | 33.4k | if (parser->states[2].crlf) { |
1885 | 4.68k | p = parser->buffer; |
1886 | 4.68k | q = p + parser->bufferSize - 1; |
1887 | 4.68k | s = parser->states[2].raw; |
1888 | 4.68k | c = *s++; |
1889 | 543k | while (c) { |
1890 | 538k | if ((c == 10) || (c == 13)) { |
1891 | 19.2k | if (before) |
1892 | 8.31k | p = before; |
1893 | 10.9k | else |
1894 | 10.9k | before = p; |
1895 | 19.2k | after = p; |
1896 | 19.2k | } |
1897 | 519k | else if ((c == 9) || (c == 32)) { |
1898 | 36.8k | if (!before) |
1899 | 26.8k | before = p; |
1900 | 36.8k | *p++ = c; |
1901 | 36.8k | } |
1902 | 482k | else { |
1903 | 482k | if (after) { |
1904 | 10.5k | p = after; |
1905 | 10.5k | if (text) |
1906 | 10.1k | *p++ = 32; |
1907 | 10.5k | } |
1908 | 482k | after = C_NULL; |
1909 | 482k | before = C_NULL; |
1910 | 482k | text = p; |
1911 | 482k | *p++ = c; |
1912 | 482k | } |
1913 | 538k | c = *s++; |
1914 | 538k | } |
1915 | 4.68k | if (after) |
1916 | 2.55k | p = after; |
1917 | 4.68k | } |
1918 | 33.4k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
1919 | 33.4k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
1920 | | |
1921 | 33.4k | parser->states[0] = parser->states[2]; |
1922 | 33.4k | parser->ahead = 0; |
1923 | 33.4k | } |
1924 | | |
1925 | | |
1926 | | |
1927 | | |
1928 | | |
1929 | | |
1930 | | |
1931 | | |
1932 | | |
1933 | | |
1934 | | |
1935 | | |
1936 | | |
1937 | | |
1938 | | |
1939 | | |