/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 | 1.93M | #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 | 125k | #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 | 25.0M | { |
114 | 25.0M | if (string + mxStringByteLength(character) > limit) { |
115 | 34 | fxReportMemoryError(parser, parser->states[2].line, "buffer overflow"); |
116 | 34 | } |
117 | 25.0M | return mxStringByteEncode(string, character); |
118 | 25.0M | } |
119 | | |
120 | | void fxCheckStrictKeyword(txParser* parser) |
121 | 7.07k | { |
122 | 7.07k | int low, high, anIndex, aDelta; |
123 | 23.6k | for (low = 0, high = XS_STRICT_KEYWORD_COUNT; high > low; |
124 | 20.1k | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
125 | 20.1k | anIndex = low + ((high - low) / 2); |
126 | 20.1k | aDelta = c_strcmp(gxStrictKeywords[anIndex].text, parser->buffer); |
127 | 20.1k | if (aDelta == 0) { |
128 | 3.56k | parser->states[0].token = gxStrictKeywords[anIndex].token; |
129 | 3.56k | goto bail; |
130 | 3.56k | } |
131 | 20.1k | } |
132 | 7.07k | bail: |
133 | 7.07k | if (parser->states[0].escaped) |
134 | 0 | fxReportParserError(parser, parser->states[0].line, "escaped keyword"); |
135 | 7.07k | } |
136 | | |
137 | | void fxGetNextCharacter(txParser* parser) |
138 | 64.3M | { |
139 | 64.3M | parser->character = parser->lookahead; |
140 | 64.3M | if (parser->character != (txU4)C_EOF) { |
141 | 64.1M | #if mxCESU8 |
142 | 64.1M | txU4 character = parser->surrogate; |
143 | 64.1M | if (character) |
144 | 13.9k | parser->surrogate = 0; |
145 | 64.1M | else |
146 | 64.1M | character = fxGetNextCode(parser); |
147 | 64.1M | if ((0x0000D800 <= character) && (character <= 0x0000DBFF)) { |
148 | 33.9k | txU4 surrogate = fxGetNextCode(parser); |
149 | 33.9k | if ((0x0000DC00 <= surrogate) && (surrogate <= 0x0000DFFF)) |
150 | 20.0k | character = 0x00010000 + ((character & 0x000003FF) << 10) + (surrogate & 0x000003FF); |
151 | 13.9k | else |
152 | 13.9k | parser->surrogate = surrogate; |
153 | 33.9k | } |
154 | 64.1M | parser->lookahead = character; |
155 | | #else |
156 | | parser->lookahead = fxGetNextCode(parser); |
157 | | #endif |
158 | 64.1M | } |
159 | 64.3M | } |
160 | | |
161 | | txU4 fxGetNextCode(txParser* parser) |
162 | 64.1M | { |
163 | 64.1M | txU4 code = (txU4)(*(parser->getter))(parser->stream); |
164 | 64.1M | if ((code & 0x80) && (code != (txU4)C_EOF)) { |
165 | 9.37M | txUTF8Sequence const *sequence = NULL; |
166 | 25.1M | for (sequence = gxUTF8Sequences; sequence->size; sequence++) { |
167 | 25.1M | if ((code & sequence->cmask) == sequence->cval) |
168 | 9.37M | break; |
169 | 25.1M | } |
170 | 9.37M | 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 | 9.37M | else { |
175 | 9.37M | txS4 size = sequence->size - 1; |
176 | 25.1M | while (size) { |
177 | 15.8M | size--; |
178 | 15.8M | code = (code << 6) | ((*(parser->getter))(parser->stream) & 0x3F); |
179 | 15.8M | } |
180 | 9.37M | code &= sequence->lmask; |
181 | 9.37M | } |
182 | 9.37M | if (code == 0x000110000) |
183 | 0 | code = 0; |
184 | 9.37M | } |
185 | 64.1M | return code; |
186 | 64.1M | } |
187 | | |
188 | | txString fxGetNextDigits(txParser* parser, txString (*f)(txParser*, txString, txString), txString p, txString q, int empty) |
189 | 390k | { |
190 | 390k | int separator = 0; |
191 | 393k | for (;;) { |
192 | 393k | txString r = p; |
193 | 393k | p = (*f)(parser, p, q); |
194 | 393k | if (r < p) { |
195 | 375k | empty = 0; |
196 | 375k | separator = 0; |
197 | 375k | if (parser->character == '_') { |
198 | 3.15k | fxGetNextCharacter(parser); |
199 | 3.15k | separator = 1; |
200 | 3.15k | } |
201 | 372k | else |
202 | 372k | break; |
203 | 375k | } |
204 | 18.3k | else |
205 | 18.3k | break; |
206 | 393k | } |
207 | 390k | if (empty || separator) |
208 | 5.19k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
209 | 390k | return p; |
210 | 390k | } |
211 | | |
212 | | txString fxGetNextDigitsB(txParser* parser, txString p, txString q) |
213 | 529 | { |
214 | 529 | int c = parser->character; |
215 | 2.77k | while (('0' <= c) && (c <= '1')) { |
216 | 2.24k | if (p < q) *p++ = (char)c; |
217 | 2.24k | fxGetNextCharacter(parser); |
218 | 2.24k | c = parser->character; |
219 | 2.24k | } |
220 | 529 | return p; |
221 | 529 | } |
222 | | |
223 | | txString fxGetNextDigitsD(txParser* parser, txString p, txString q, int* base) |
224 | 4.38k | { |
225 | 4.38k | int c = parser->character; |
226 | 4.38k | *base = 8; |
227 | 297k | while (('0' <= c) && (c <= '9')) { |
228 | 292k | if (p < q) *p++ = (char)c; |
229 | 292k | if (('8' <= c) && (c <= '9')) |
230 | 5.17k | *base = 10; |
231 | 292k | fxGetNextCharacter(parser); |
232 | 292k | c = parser->character; |
233 | 292k | } |
234 | 4.38k | return p; |
235 | 4.38k | } |
236 | | |
237 | | txString fxGetNextDigitsE(txParser* parser, txString p, txString q) |
238 | 264k | { |
239 | 264k | int c = parser->character; |
240 | 1.50M | while (('0' <= c) && (c <= '9')) { |
241 | 1.24M | if (p < q) *p++ = (char)c; |
242 | 1.24M | fxGetNextCharacter(parser); |
243 | 1.24M | c = parser->character; |
244 | 1.24M | } |
245 | 264k | return p; |
246 | 264k | } |
247 | | |
248 | | txString fxGetNextDigitsO(txParser* parser, txString p, txString q) |
249 | 1.45k | { |
250 | 1.45k | int c = parser->character; |
251 | 4.72k | while (('0' <= c) && (c <= '7')) { |
252 | 3.27k | if (p < q) *p++ = (char)c; |
253 | 3.27k | fxGetNextCharacter(parser); |
254 | 3.27k | c = parser->character; |
255 | 3.27k | } |
256 | 1.45k | return p; |
257 | 1.45k | } |
258 | | |
259 | | txString fxGetNextDigitsX(txParser* parser, txString p, txString q) |
260 | 126k | { |
261 | 126k | int c = parser->character; |
262 | 1.04M | while ((('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'))) { |
263 | 915k | if (p < q) *p++ = (char)c; |
264 | 915k | fxGetNextCharacter(parser); |
265 | 915k | c = parser->character; |
266 | 915k | } |
267 | 126k | return p; |
268 | 126k | } |
269 | | |
270 | | void fxGetNextKeyword(txParser* parser) |
271 | 2.15M | { |
272 | 2.15M | int low, high, anIndex, aDelta; |
273 | | |
274 | 2.15M | parser->states[2].symbol = fxNewParserSymbol(parser, parser->buffer); |
275 | 2.15M | parser->states[2].token = XS_TOKEN_IDENTIFIER; |
276 | 2.15M | if ((parser->states[0].token == XS_TOKEN_DOT) || (parser->states[0].token == XS_TOKEN_CHAIN)) |
277 | 215k | return; |
278 | 11.4M | for (low = 0, high = XS_KEYWORD_COUNT; high > low; |
279 | 10.0M | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
280 | 10.0M | anIndex = low + ((high - low) / 2); |
281 | 10.0M | aDelta = c_strcmp(gxKeywords[anIndex].text, parser->buffer); |
282 | 10.0M | if (aDelta == 0) { |
283 | 516k | parser->states[2].token = gxKeywords[anIndex].token; |
284 | 516k | return; |
285 | 516k | } |
286 | 10.0M | } |
287 | 1.41M | if ((parser->flags & mxStrictFlag)) { |
288 | 441k | for (low = 0, high = XS_STRICT_KEYWORD_COUNT; high > low; |
289 | 363k | (aDelta < 0) ? (low = anIndex + 1) : (high = anIndex)) { |
290 | 363k | anIndex = low + ((high - low) / 2); |
291 | 363k | aDelta = c_strcmp(gxStrictKeywords[anIndex].text, parser->buffer); |
292 | 363k | if (aDelta == 0) { |
293 | 40.9k | parser->states[2].token = gxStrictKeywords[anIndex].token; |
294 | 40.9k | return; |
295 | 40.9k | } |
296 | 363k | } |
297 | 118k | } |
298 | 1.37M | if (c_strcmp("await", parser->buffer) == 0) { |
299 | 1.24k | if (parser->flags & mxAsyncFlag) { |
300 | 620 | parser->states[2].token = XS_TOKEN_AWAIT; |
301 | 620 | return; |
302 | 620 | } |
303 | 1.24k | } |
304 | 1.37M | if (c_strcmp("yield", parser->buffer) == 0) { |
305 | 10.5k | if ((parser->flags & mxGeneratorFlag)){ |
306 | 7.17k | parser->states[2].token = XS_TOKEN_YIELD; |
307 | 7.17k | return; |
308 | 7.17k | } |
309 | 10.5k | } |
310 | 1.36M | return; |
311 | 1.37M | } |
312 | | |
313 | | txBoolean fxGetNextIdentiferX(txParser* parser, txU4* value) |
314 | 3.18k | { |
315 | 3.18k | fxGetNextCharacter(parser); |
316 | 3.18k | if (parser->character == 'u') { |
317 | 2.80k | fxGetNextCharacter(parser); |
318 | 2.80k | if (parser->character == '{') { |
319 | 733 | fxGetNextCharacter(parser); |
320 | 3.70k | while (fxGetNextStringX(parser->character, value)) { |
321 | 2.97k | fxGetNextCharacter(parser); |
322 | 2.97k | } |
323 | 733 | if (parser->character == '}') { |
324 | 135 | fxGetNextCharacter(parser); |
325 | 135 | return 1; |
326 | 135 | } |
327 | 733 | } |
328 | 2.07k | else { |
329 | 2.07k | if (fxGetNextStringX(parser->character, value)) { |
330 | 2.05k | fxGetNextCharacter(parser); |
331 | 2.05k | if (fxGetNextStringX(parser->character, value)) { |
332 | 1.87k | fxGetNextCharacter(parser); |
333 | 1.87k | if (fxGetNextStringX(parser->character, value)) { |
334 | 1.75k | fxGetNextCharacter(parser); |
335 | 1.75k | if (fxGetNextStringX(parser->character, value)) { |
336 | 632 | fxGetNextCharacter(parser); |
337 | 632 | return 1; |
338 | 632 | } |
339 | 1.75k | } |
340 | 1.87k | } |
341 | 2.05k | } |
342 | 2.07k | } |
343 | 2.80k | } |
344 | 2.41k | return 0; |
345 | 3.18k | } |
346 | | |
347 | | void fxGetNextNumber(txParser* parser, txNumber theNumber) |
348 | 316k | { |
349 | 316k | parser->states[2].number = theNumber; |
350 | 316k | parser->states[2].integer = (txInteger)parser->states[2].number; |
351 | 316k | theNumber = parser->states[2].integer; |
352 | 316k | if (parser->states[2].number == theNumber) |
353 | 290k | parser->states[2].token = XS_TOKEN_INTEGER; |
354 | 25.7k | else |
355 | 25.7k | parser->states[2].token = XS_TOKEN_NUMBER; |
356 | 316k | } |
357 | | |
358 | | void fxGetNextNumberB(txParser* parser) |
359 | 438 | { |
360 | 438 | txString p = parser->buffer; |
361 | 438 | txString q = p + parser->bufferSize; |
362 | 438 | int c; |
363 | 438 | fxGetNextCharacter(parser); |
364 | 438 | p = fxGetNextDigits(parser, fxGetNextDigitsB, p, q, 1); |
365 | 438 | c = parser->character; |
366 | 438 | if (p == q) { |
367 | 0 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
368 | 0 | } |
369 | 438 | if (c == 'n') |
370 | 17 | fxGetNextCharacter(parser); |
371 | 438 | if (fxIsIdentifierFirst(parser->character)) { |
372 | 29 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
373 | 29 | } |
374 | 438 | *p = 0; |
375 | 438 | q = parser->buffer; |
376 | 438 | 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 | 421 | else { |
382 | 421 | txNumber n = 0; |
383 | 1.45k | while ((c = *q++)) |
384 | 1.02k | n = (n * 2) + (c - '0'); |
385 | 421 | fxGetNextNumber(parser, n); |
386 | 421 | } |
387 | 438 | } |
388 | | |
389 | | void fxGetNextNumberE(txParser* parser, int dot) |
390 | 234k | { |
391 | 234k | txString p = parser->buffer; |
392 | 234k | txString q = p + parser->bufferSize; |
393 | 234k | txString r; |
394 | 234k | int c; |
395 | 234k | if (dot) { |
396 | 8.07k | if (p < q) *p++ = '.'; |
397 | 8.07k | } |
398 | 234k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 0); |
399 | 234k | if (dot) |
400 | 8.07k | r = p; |
401 | 226k | else if (parser->character == '.') { |
402 | 14.9k | dot = 1; |
403 | 14.9k | if (p < q) *p++ = '.'; |
404 | 14.9k | fxGetNextCharacter(parser); |
405 | 14.9k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 0); |
406 | 14.9k | r = p; |
407 | 14.9k | } |
408 | 234k | c = parser->character; |
409 | 234k | if ((c == 'e') || (c == 'E')) { |
410 | 12.8k | if (dot) { |
411 | 8.31k | if (p == r) { |
412 | 8.31k | if (p < q) *p++ = '0'; |
413 | 8.31k | } |
414 | 8.31k | } |
415 | 4.51k | else { |
416 | 4.51k | dot = 1; |
417 | 4.51k | if (p < q) *p++ = '.'; |
418 | 4.51k | if (p < q) *p++ = '0'; |
419 | 4.51k | } |
420 | 12.8k | if (p < q) *p++ = (char)c; |
421 | 12.8k | fxGetNextCharacter(parser); |
422 | 12.8k | c = parser->character; |
423 | 12.8k | if ((c == '+') || (c == '-')) { |
424 | 5.55k | if (p < q) *p++ = (char)c; |
425 | 5.55k | fxGetNextCharacter(parser); |
426 | 5.55k | c = parser->character; |
427 | 5.55k | } |
428 | 12.8k | p = fxGetNextDigits(parser, fxGetNextDigitsE, p, q, 1); |
429 | 12.8k | c = parser->character; |
430 | 12.8k | } |
431 | 234k | if (p == q) { |
432 | 6 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
433 | 6 | } |
434 | 234k | if (c == 'n') |
435 | 40.7k | fxGetNextCharacter(parser); |
436 | 234k | if (fxIsIdentifierFirst(parser->character)) { |
437 | 4.33k | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
438 | 4.33k | } |
439 | 234k | *p = 0; |
440 | 234k | q = parser->buffer; |
441 | 234k | if (c == 'n') { |
442 | 39.7k | if (dot == 0) { |
443 | 39.7k | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximum(mxPtrDiff(p - q))); |
444 | 39.7k | fxBigIntParse(&parser->states[2].bigint, q, mxPtrDiff(p - q), 0); |
445 | 39.7k | parser->states[2].token = XS_TOKEN_BIGINT; |
446 | 39.7k | } |
447 | 35 | else |
448 | 35 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
449 | 39.7k | } |
450 | 194k | else |
451 | 194k | fxGetNextNumber(parser, fxStringToNumber(parser->console, parser->buffer, 1)); |
452 | 234k | } |
453 | | |
454 | | void fxGetNextNumberO(txParser* parser, int c, int legacy) |
455 | 5.53k | { |
456 | 5.53k | txString p = parser->buffer; |
457 | 5.53k | txString q = p + parser->bufferSize; |
458 | 5.53k | if (legacy) { |
459 | 4.38k | p = fxGetNextDigitsD(parser, p, q, &legacy); |
460 | 4.38k | if (parser->character == '_') |
461 | 102 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
462 | 4.38k | if (parser->character == 'n') |
463 | 82 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
464 | 4.38k | } |
465 | 1.14k | else { |
466 | 1.14k | fxGetNextCharacter(parser); |
467 | 1.14k | legacy = 8; |
468 | 1.14k | p = fxGetNextDigits(parser, fxGetNextDigitsO, p, q, 1); |
469 | 1.14k | } |
470 | 5.53k | c = parser->character; |
471 | 5.53k | if (p == q) { |
472 | 3 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
473 | 3 | } |
474 | 5.53k | if (c == 'n') |
475 | 212 | fxGetNextCharacter(parser); |
476 | 5.53k | if (fxIsIdentifierFirst(parser->character)) { |
477 | 769 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
478 | 769 | } |
479 | 5.53k | *p = 0; |
480 | 5.53k | q = parser->buffer; |
481 | 5.53k | if (c == 'n') { |
482 | 212 | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximumO(mxPtrDiff(p - q))); |
483 | 212 | fxBigIntParseO(&parser->states[2].bigint, q, mxPtrDiff(p - q)); |
484 | 212 | parser->states[2].token = XS_TOKEN_BIGINT; |
485 | 212 | } |
486 | 5.31k | else { |
487 | 5.31k | txNumber n = 0; |
488 | 60.0k | while ((c = *q++)) |
489 | 54.7k | n = (n * legacy) + (c - '0'); |
490 | 5.31k | fxGetNextNumber(parser, n); |
491 | 5.31k | } |
492 | 5.53k | } |
493 | | |
494 | | void fxGetNextNumberX(txParser* parser) |
495 | 126k | { |
496 | 126k | txString p = parser->buffer; |
497 | 126k | txString q = p + parser->bufferSize; |
498 | 126k | int c; |
499 | 126k | fxGetNextCharacter(parser); |
500 | 126k | p = fxGetNextDigits(parser, fxGetNextDigitsX, p, q, 1); |
501 | 126k | c = parser->character; |
502 | 126k | if (p == q) { |
503 | 5 | fxReportMemoryError(parser, parser->states[2].line, "number overflow"); |
504 | 5 | } |
505 | 126k | if (c == 'n') |
506 | 513 | fxGetNextCharacter(parser); |
507 | 126k | if (fxIsIdentifierFirst(parser->character)) { |
508 | 45 | fxReportParserError(parser, parser->states[2].line, "invalid number"); |
509 | 45 | } |
510 | 126k | *p = 0; |
511 | 126k | q = parser->buffer; |
512 | 126k | if (c == 'n') { |
513 | 513 | parser->states[2].bigint.data = fxNewParserChunk(parser, fxBigIntMaximumX(mxPtrDiff(p - q))); |
514 | 513 | fxBigIntParseX(&parser->states[2].bigint, q, mxPtrDiff(p - q)); |
515 | 513 | parser->states[2].token = XS_TOKEN_BIGINT; |
516 | 513 | } |
517 | 126k | else { |
518 | 126k | txNumber n = 0; |
519 | 673k | while ((c = *q++)) { |
520 | 547k | if (('0' <= c) && (c <= '9')) |
521 | 420k | n = (n * 16) + (c - '0'); |
522 | 126k | else if (('a' <= c) && (c <= 'f')) |
523 | 12.5k | n = (n * 16) + (10 + c - 'a'); |
524 | 113k | else |
525 | 113k | n = (n * 16) + (10 + c - 'A'); |
526 | 547k | } |
527 | 126k | fxGetNextNumber(parser, n); |
528 | 126k | } |
529 | 126k | } |
530 | | |
531 | | void fxGetNextRegExp(txParser* parser, txU4 c) |
532 | 10.6k | { |
533 | 10.6k | txString p; |
534 | 10.6k | txString q; |
535 | 10.6k | txBoolean backslash = 0; |
536 | 10.6k | txBoolean bracket = 0; |
537 | 10.6k | txBoolean first = 1; |
538 | 10.6k | txBoolean second = 1; |
539 | 10.6k | p = parser->buffer; |
540 | 10.6k | q = p + parser->bufferSize - 1; |
541 | 10.6k | if (!c) { |
542 | 10.1k | c = parser->character; |
543 | 10.1k | second = 0; |
544 | 10.1k | } |
545 | 656k | for (;;) { |
546 | 656k | if (c == (txU4)C_EOF) { |
547 | 1.04k | fxReportParserError(parser, parser->states[0].line, "end of file in regular expression"); |
548 | 1.04k | break; |
549 | 1.04k | } |
550 | 654k | else if ((c == 10) || (c == 13) || (c == 0x2028) || (c == 0x2029)) { |
551 | 300 | fxReportParserError(parser, parser->states[0].line, "end of line in regular expression"); |
552 | 300 | break; |
553 | 300 | } |
554 | 654k | else if (c == '*') { |
555 | 1.19k | if (first) { |
556 | 1 | fxReportParserError(parser, parser->states[0].line, "invalid regular expression"); |
557 | 1 | break; |
558 | 1 | } |
559 | 1.19k | backslash = 0; |
560 | 1.19k | } |
561 | 653k | else if (c == '\\') { |
562 | 22.1k | if (!backslash) |
563 | 19.2k | backslash = 1; |
564 | 2.95k | else |
565 | 2.95k | backslash = 0; |
566 | 22.1k | } |
567 | 631k | else if (c == '[') { |
568 | 31.0k | if (!backslash) |
569 | 28.6k | bracket = 1; |
570 | 31.0k | backslash = 0; |
571 | 31.0k | } |
572 | 600k | else if (c == ']') { |
573 | 4.46k | if (!backslash) |
574 | 4.42k | bracket = 0; |
575 | 4.46k | backslash = 0; |
576 | 4.46k | } |
577 | 595k | else if (c == '/') { |
578 | 12.8k | if (!backslash && !bracket) |
579 | 9.31k | break; |
580 | 3.53k | backslash = 0; |
581 | 3.53k | } |
582 | 582k | else { |
583 | 582k | backslash = 0; |
584 | 582k | } |
585 | 645k | p = fxUTF8Buffer(parser, c, p, q); |
586 | 645k | if (second) |
587 | 548 | second = 0; |
588 | 644k | else |
589 | 644k | fxGetNextCharacter(parser); |
590 | 645k | c = parser->character; |
591 | 645k | first = 0; |
592 | 645k | } |
593 | 10.6k | *p = 0; |
594 | 10.6k | parser->states[0].stringLength = mxPtrDiff(p - parser->buffer); |
595 | 10.6k | parser->states[0].string = fxNewParserString(parser, parser->buffer, parser->states[0].stringLength); |
596 | 10.6k | p = parser->buffer; |
597 | 10.6k | q = p + parser->bufferSize - 1; |
598 | 15.8k | for (;;) { |
599 | 15.8k | fxGetNextCharacter(parser); |
600 | 15.8k | if (fxIsIdentifierNext(parser->character)) |
601 | 6.50k | p = fxUTF8Buffer(parser, parser->character, p, q); |
602 | 9.31k | else |
603 | 9.31k | break; |
604 | 15.8k | } |
605 | 10.6k | *p = 0; |
606 | 10.6k | parser->states[0].modifierLength = mxPtrDiff(p - parser->buffer); |
607 | 10.6k | parser->states[0].modifier = fxNewParserString(parser, parser->buffer, parser->states[0].modifierLength); |
608 | 10.6k | if (!fxCompileRegExp(parser->console, parser->states[0].string, parser->states[0].modifier, C_NULL, C_NULL, parser->buffer, parser->bufferSize)) |
609 | 1.57k | fxReportParserError(parser, parser->states[0].line, "%s", parser->buffer); |
610 | 10.6k | parser->states[0].token = XS_TOKEN_REGEXP; |
611 | 10.6k | } |
612 | | |
613 | | void fxGetNextString(txParser* parser, int c) |
614 | 452k | { |
615 | 452k | txString p = parser->buffer; |
616 | 452k | txString q = p + parser->bufferSize - 1; |
617 | 9.00M | for (;;) { |
618 | 9.00M | if (parser->character == (txU4)C_EOF) { |
619 | 1.99k | fxReportParserError(parser, parser->states[2].line, "end of file in string"); |
620 | 1.99k | break; |
621 | 1.99k | } |
622 | 9.00M | else if (parser->character == 10) { |
623 | 117k | parser->states[2].line++; |
624 | 117k | if (c == '`') { |
625 | 114k | p = fxUTF8Buffer(parser, parser->character, p, q); |
626 | 114k | fxGetNextCharacter(parser); |
627 | 114k | } |
628 | 2.91k | else { |
629 | 2.91k | fxReportParserError(parser, parser->states[2].line, "end of line in string"); |
630 | 2.91k | break; |
631 | 2.91k | } |
632 | 117k | } |
633 | 8.89M | else if (parser->character == 13) { |
634 | 30.3k | parser->states[2].line++; |
635 | 30.3k | if (c == '`') { |
636 | 30.3k | p = fxUTF8Buffer(parser, 10, p, q); |
637 | 30.3k | fxGetNextCharacter(parser); |
638 | 30.3k | if (parser->character == 10) |
639 | 15.4k | fxGetNextCharacter(parser); |
640 | 30.3k | } |
641 | 2 | else { |
642 | 2 | fxReportParserError(parser, parser->states[2].line, "end of line in string"); |
643 | 2 | break; |
644 | 2 | } |
645 | 30.3k | } |
646 | 8.85M | else if ((parser->character == 0x2028) || (parser->character == 0x2029)) { |
647 | 2.57k | parser->states[2].line++; |
648 | 2.57k | p = fxUTF8Buffer(parser, parser->character, p, q); |
649 | 2.57k | fxGetNextCharacter(parser); |
650 | 2.57k | } |
651 | 8.85M | else if (parser->character == (txU4)c) { |
652 | 440k | break; |
653 | 440k | } |
654 | 8.41M | else if (parser->character == '$') { |
655 | 18.3k | fxGetNextCharacter(parser); |
656 | 18.3k | if ((c == '`') && (parser->character == '{')) |
657 | 6.95k | break; |
658 | 11.4k | p = fxUTF8Buffer(parser, '$', p, q); |
659 | 11.4k | } |
660 | 8.39M | else if (parser->character == '\\') { |
661 | 137k | parser->states[2].escaped = 1; |
662 | 137k | p = fxUTF8Buffer(parser, '\\', p, q); |
663 | 137k | fxGetNextCharacter(parser); |
664 | 137k | switch (parser->character) { |
665 | 544 | case 10: |
666 | 1.07k | case 0x2028: |
667 | 1.12k | case 0x2029: |
668 | 1.12k | parser->states[2].line++; |
669 | 1.12k | p = fxUTF8Buffer(parser, parser->character, p, q); |
670 | 1.12k | fxGetNextCharacter(parser); |
671 | 1.12k | break; |
672 | 506 | case 13: |
673 | 506 | parser->states[2].line++; |
674 | 506 | p = fxUTF8Buffer(parser, 10, p, q); |
675 | 506 | fxGetNextCharacter(parser); |
676 | 506 | if (parser->character == 10) |
677 | 460 | fxGetNextCharacter(parser); |
678 | 506 | break; |
679 | 135k | default: |
680 | 135k | p = fxUTF8Buffer(parser, parser->character, p, q); |
681 | 135k | fxGetNextCharacter(parser); |
682 | 135k | break; |
683 | 137k | } |
684 | 137k | } |
685 | 8.26M | else { |
686 | 8.26M | p = fxUTF8Buffer(parser, parser->character, p, q); |
687 | 8.26M | fxGetNextCharacter(parser); |
688 | 8.26M | } |
689 | 9.00M | } |
690 | 452k | *p = 0; |
691 | 452k | if (p == q) { |
692 | 0 | fxReportMemoryError(parser, parser->states[2].line, "string overflow"); |
693 | 0 | } |
694 | 452k | parser->states[2].rawLength = mxPtrDiff(p - parser->buffer); |
695 | 452k | parser->states[2].raw = fxNewParserString(parser, parser->buffer, parser->states[2].rawLength); |
696 | 452k | if (parser->states[2].escaped) { |
697 | 17.1k | txInteger character; |
698 | 17.1k | txString s; |
699 | 17.1k | txU1* u; |
700 | 17.1k | p = parser->buffer; |
701 | 17.1k | q = p + parser->bufferSize - 1; |
702 | 17.1k | s = parser->states[2].raw; |
703 | 5.54M | while (*s) { |
704 | 5.53M | if (p == q) { |
705 | 0 | fxReportMemoryError(parser, parser->states[2].line, "buffer overflow"); |
706 | 0 | } |
707 | 5.53M | if (*s == '\\') { |
708 | 134k | s++; |
709 | 134k | switch (*s) { |
710 | 0 | case 0: |
711 | 0 | break; |
712 | 727 | case 10: |
713 | 727 | s++; |
714 | 727 | break; |
715 | 0 | case 13: |
716 | 0 | s++; |
717 | 0 | if (*s == 10) |
718 | 0 | s++; |
719 | 0 | break; |
720 | 2.88k | case 'b': |
721 | 2.88k | s++; |
722 | 2.88k | *p++ = '\b'; |
723 | 2.88k | break; |
724 | 221 | case 'f': |
725 | 221 | s++; |
726 | 221 | *p++ = '\f'; |
727 | 221 | break; |
728 | 2.71k | case 'n': |
729 | 2.71k | s++; |
730 | 2.71k | *p++ = '\n'; |
731 | 2.71k | break; |
732 | 1.48k | case 'r': |
733 | 1.48k | s++; |
734 | 1.48k | *p++ = '\r'; |
735 | 1.48k | break; |
736 | 1.54k | case 't': |
737 | 1.54k | s++; |
738 | 1.54k | *p++ = '\t'; |
739 | 1.54k | break; |
740 | 242 | case 'v': |
741 | 242 | s++; |
742 | 242 | *p++ = '\v'; |
743 | 242 | break; |
744 | 475 | case 'x': |
745 | 475 | s++; |
746 | 475 | if (fxParseHexEscape(&s, &character)) |
747 | 412 | p = fxUTF8Buffer(parser, character, p, q); |
748 | 63 | else |
749 | 63 | parser->states[2].escaped |= mxStringErrorFlag; |
750 | 475 | break; |
751 | 29.0k | case 'u': |
752 | 29.0k | s++; |
753 | 29.0k | if (fxParseUnicodeEscape(&s, &character, 1, '\\')) |
754 | 14.9k | p = fxUTF8Buffer(parser, character, p, q); |
755 | 14.0k | else |
756 | 14.0k | parser->states[2].escaped |= mxStringErrorFlag; |
757 | 29.0k | break; |
758 | 5.14k | case '0': |
759 | 6.58k | case '1': |
760 | 6.67k | case '2': |
761 | 6.76k | case '3': |
762 | 8.10k | case '4': |
763 | 9.30k | case '5': |
764 | 9.36k | case '6': |
765 | 9.41k | case '7': |
766 | 9.41k | character = *s++ - '0'; |
767 | 9.41k | if ((character == 0) && ((*s < '0') || ('9' < *s))) |
768 | 3.89k | p = fxUTF8Buffer(parser, character, p, q); |
769 | 5.51k | else { |
770 | 5.51k | parser->states[2].escaped |= mxStringLegacyFlag; |
771 | 5.51k | if ((0 <= character) && (character <= 3)) { |
772 | 2.87k | if (('0' <= *s) && (*s <= '7')) |
773 | 1.29k | character = (character * 8) + *s++ - '0'; |
774 | 2.87k | } |
775 | 5.51k | if (('0' <= *s) && (*s <= '7')) |
776 | 39 | character = (character * 8) + *s++ - '0'; |
777 | 5.51k | p = fxUTF8Buffer(parser, character, p, q); |
778 | 5.51k | } |
779 | 9.41k | break; |
780 | 45 | case '8': |
781 | 133 | case '9': |
782 | 133 | parser->states[2].escaped |= mxStringLegacyFlag; |
783 | 133 | *p++ = *s++; |
784 | 133 | break; |
785 | 85.5k | default: |
786 | 85.5k | u = (txU1*)s; |
787 | 85.5k | if ((u[0] == 0xE2) && (u[1] == 0x80) && ((u[2] == 0xA8) || (u[2] == 0xA9))) { /* LS || PS */ |
788 | 566 | s += 3; |
789 | 566 | } |
790 | 84.9k | else |
791 | 84.9k | *p++ = *s++; |
792 | 85.5k | break; |
793 | 134k | } |
794 | 134k | } |
795 | 5.39M | else { |
796 | 5.39M | *p++ = *s++; |
797 | 5.39M | } |
798 | 5.53M | } |
799 | 17.1k | *p = 0; |
800 | 17.1k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
801 | 17.1k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
802 | 17.1k | if ((c == '`') && (parser->states[2].escaped & mxStringLegacyFlag)) |
803 | 2.54k | parser->states[2].escaped |= mxStringErrorFlag; |
804 | 17.1k | } |
805 | 435k | else { |
806 | 435k | parser->states[2].stringLength = parser->states[2].rawLength; |
807 | 435k | parser->states[2].string = parser->states[2].raw; |
808 | 435k | } |
809 | 452k | } |
810 | | |
811 | | txBoolean fxGetNextStringD(int c, txU4* value) |
812 | 2.33k | { |
813 | 2.33k | if (('0' <= c) && (c <= '9')) |
814 | 1.22k | *value = (*value * 10) + (c - '0'); |
815 | 1.10k | else |
816 | 1.10k | return 0; |
817 | 1.22k | return 1; |
818 | 2.33k | } |
819 | | |
820 | | txBoolean fxGetNextStringX(int c, txU4* value) |
821 | 24.9k | { |
822 | 24.9k | if (('0' <= c) && (c <= '9')) |
823 | 9.10k | *value = (*value * 16) + (c - '0'); |
824 | 15.8k | else if (('a' <= c) && (c <= 'f')) |
825 | 9.13k | *value = (*value * 16) + (10 + c - 'a'); |
826 | 6.69k | else if (('A' <= c) && (c <= 'F')) |
827 | 1.92k | *value = (*value * 16) + (10 + c - 'A'); |
828 | 4.76k | else |
829 | 4.76k | return 0; |
830 | 20.1k | return 1; |
831 | 24.9k | } |
832 | | |
833 | | void fxGetNextToken(txParser* parser) |
834 | 16.1M | { |
835 | 16.1M | if (parser->ahead == 0) { |
836 | 15.4M | fxGetNextTokenAux(parser); |
837 | 15.4M | parser->states[0] = parser->states[2]; |
838 | 15.4M | } |
839 | 668k | else if (parser->ahead == 1) { |
840 | 668k | parser->states[0] = parser->states[1]; |
841 | 668k | parser->ahead = 0; |
842 | 668k | } |
843 | 4 | else if (parser->ahead == 2) { |
844 | 4 | parser->states[0] = parser->states[1]; |
845 | 4 | parser->states[1] = parser->states[2]; |
846 | 4 | parser->ahead = 1; |
847 | 4 | } |
848 | 16.1M | } |
849 | | |
850 | | void fxLookAheadOnce(txParser* parser) |
851 | 690k | { |
852 | 690k | if (parser->ahead == 0) { |
853 | 690k | fxGetNextTokenAux(parser); |
854 | 690k | parser->states[1] = parser->states[2]; |
855 | 690k | parser->ahead = 1; |
856 | 690k | } |
857 | 690k | } |
858 | | |
859 | | void fxLookAheadTwice(txParser* parser) |
860 | 4 | { |
861 | 4 | 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 | 4 | else if (parser->ahead == 1) { |
868 | 4 | fxGetNextTokenAux(parser); |
869 | 4 | parser->ahead = 2; |
870 | 4 | } |
871 | 4 | } |
872 | | |
873 | | void fxGetNextTokenAux(txParser* parser) |
874 | 16.1M | { |
875 | 16.1M | int c; |
876 | 16.1M | txString p; |
877 | 16.1M | txString q; |
878 | 16.1M | txU4 t = 0; |
879 | 16.1M | parser->states[2].crlf = 0; |
880 | 16.1M | parser->states[2].escaped = 0; |
881 | 16.1M | parser->states[2].bigint.data = C_NULL; |
882 | 16.1M | parser->states[2].bigint.size = 0; |
883 | 16.1M | parser->states[2].bigint.sign = 0; |
884 | 16.1M | parser->states[2].integer = 0; |
885 | 16.1M | parser->states[2].modifierLength = 0; |
886 | 16.1M | parser->states[2].modifier = parser->emptyString; |
887 | 16.1M | parser->states[2].number = 0; |
888 | 16.1M | parser->states[2].rawLength = 0; |
889 | 16.1M | parser->states[2].raw = parser->emptyString; |
890 | 16.1M | parser->states[2].stringLength = 0; |
891 | 16.1M | parser->states[2].string = parser->emptyString; |
892 | 16.1M | parser->states[2].symbol = C_NULL; |
893 | 16.1M | parser->states[2].token = XS_NO_TOKEN; |
894 | 35.7M | while (parser->states[2].token == XS_NO_TOKEN) { |
895 | 19.6M | switch (parser->character) { |
896 | 219k | case C_EOF: |
897 | 219k | parser->states[2].token = XS_TOKEN_EOF; |
898 | 219k | break; |
899 | 1.21M | case 10: |
900 | 1.21M | case 0x2028: // <LS> |
901 | 1.21M | case 0x2029: // <PS> |
902 | 1.21M | parser->states[2].line++; |
903 | 1.21M | fxGetNextCharacter(parser); |
904 | 1.21M | parser->states[2].crlf = 1; |
905 | 1.21M | break; |
906 | 42.2k | case 13: |
907 | 42.2k | parser->states[2].line++; |
908 | 42.2k | fxGetNextCharacter(parser); |
909 | 42.2k | if (parser->character == 10) |
910 | 23.5k | fxGetNextCharacter(parser); |
911 | 42.2k | parser->states[2].crlf = 1; |
912 | 42.2k | break; |
913 | | |
914 | 120k | case '\t': |
915 | 241k | case 11: |
916 | 266k | case 12: |
917 | 2.03M | case ' ': |
918 | 2.03M | case 0x00A0: |
919 | 2.03M | case 0x1680: |
920 | 2.03M | case 0x2000: |
921 | 2.03M | case 0x2001: |
922 | 2.03M | case 0x2002: |
923 | 2.04M | case 0x2003: |
924 | 2.04M | case 0x2004: |
925 | 2.04M | case 0x2005: |
926 | 2.04M | case 0x2006: |
927 | 2.05M | case 0x2007: |
928 | 2.05M | case 0x2008: |
929 | 2.05M | case 0x2009: |
930 | 2.05M | case 0x200A: |
931 | 2.05M | case 0x202F: |
932 | 2.05M | case 0x205F: |
933 | 2.05M | case 0x3000: |
934 | 2.05M | case 0xFEFF: |
935 | 2.05M | fxGetNextCharacter(parser); |
936 | 2.05M | break; |
937 | | |
938 | 4.66M | case '0': |
939 | 4.66M | fxGetNextCharacter(parser); |
940 | 4.66M | c = parser->character; |
941 | 4.66M | if (c == '.') { |
942 | 5.49k | fxGetNextCharacter(parser); |
943 | 5.49k | c = parser->character; |
944 | 5.49k | if ((('0' <= c) && (c <= '9')) || (c == 'e') || (c == 'E')) |
945 | 4.65k | fxGetNextNumberE(parser, 1); |
946 | 838 | else { |
947 | 838 | parser->states[2].number = 0; |
948 | 838 | parser->states[2].token = XS_TOKEN_NUMBER; |
949 | 838 | } |
950 | 5.49k | } |
951 | 4.65M | else if ((c == 'b') || (c == 'B')) { |
952 | 438 | fxGetNextNumberB(parser); |
953 | 438 | } |
954 | 4.65M | else if ((c == 'e') || (c == 'E')) { |
955 | 1.26k | fxGetNextNumberE(parser, 0); |
956 | 1.26k | } |
957 | 4.65M | else if (c == 'n') { |
958 | 7.21k | fxGetNextNumberE(parser, 0); |
959 | 7.21k | } |
960 | 4.64M | else if ((c == 'o') || (c == 'O')) { |
961 | 1.14k | fxGetNextNumberO(parser, '0', 0); |
962 | 1.14k | } |
963 | 4.64M | else if ((c == 'x') || (c == 'X')) { |
964 | 126k | fxGetNextNumberX(parser); |
965 | 126k | } |
966 | 4.51M | else if (('0' <= c) && (c <= '9')) { |
967 | 4.40k | if ((parser->flags & mxStrictFlag)) |
968 | 14 | fxReportParserError(parser, parser->states[2].line, "octal number (strict mode)"); |
969 | 4.40k | fxGetNextNumberO(parser, c, 1); |
970 | 4.40k | } |
971 | 4.51M | else { |
972 | 4.51M | parser->states[2].integer = 0; |
973 | 4.51M | parser->states[2].token = XS_TOKEN_INTEGER; |
974 | 4.51M | } |
975 | 4.66M | break; |
976 | 65.8k | case '1': |
977 | 112k | case '2': |
978 | 155k | case '3': |
979 | 170k | case '4': |
980 | 184k | case '5': |
981 | 198k | case '6': |
982 | 203k | case '7': |
983 | 208k | case '8': |
984 | 217k | case '9': |
985 | 217k | fxGetNextNumberE(parser, 0); |
986 | 217k | break; |
987 | 239k | case '.': |
988 | 239k | fxGetNextCharacter(parser); |
989 | 239k | c = parser->character; |
990 | 239k | if (c == '.') { |
991 | 5.29k | fxGetNextCharacter(parser); |
992 | 5.29k | if (parser->character == '.') { |
993 | 4.90k | parser->states[2].token = XS_TOKEN_SPREAD; |
994 | 4.90k | fxGetNextCharacter(parser); |
995 | 4.90k | } |
996 | 390 | else { |
997 | 390 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
998 | 390 | } |
999 | 5.29k | } |
1000 | 234k | else if (('0' <= c) && (c <= '9')) |
1001 | 3.42k | fxGetNextNumberE(parser, 1); |
1002 | 230k | else |
1003 | 230k | parser->states[2].token = XS_TOKEN_DOT; |
1004 | 239k | break; |
1005 | 432k | case ',': |
1006 | 432k | parser->states[2].token = XS_TOKEN_COMMA; |
1007 | 432k | fxGetNextCharacter(parser); |
1008 | 432k | break; |
1009 | 284k | case ';': |
1010 | 284k | parser->states[2].token = XS_TOKEN_SEMICOLON; |
1011 | 284k | fxGetNextCharacter(parser); |
1012 | 284k | break; |
1013 | 152k | case ':': |
1014 | 152k | parser->states[2].token = XS_TOKEN_COLON; |
1015 | 152k | fxGetNextCharacter(parser); |
1016 | 152k | break; |
1017 | 14.3k | case '?': |
1018 | 14.3k | fxGetNextCharacter(parser); |
1019 | 14.3k | if (parser->character == '.') { |
1020 | 5.77k | if ((parser->lookahead < '0') || ('9' < parser->lookahead)) { |
1021 | 5.34k | parser->states[2].token = XS_TOKEN_CHAIN; |
1022 | 5.34k | fxGetNextCharacter(parser); |
1023 | 5.34k | } |
1024 | 434 | else |
1025 | 434 | parser->states[2].token = XS_TOKEN_QUESTION_MARK; |
1026 | 5.77k | } |
1027 | 8.57k | else if (parser->character == '?') { |
1028 | 2.16k | parser->states[2].token = XS_TOKEN_COALESCE; |
1029 | 2.16k | fxGetNextCharacter(parser); |
1030 | 2.16k | if (parser->character == '=') { |
1031 | 532 | parser->states[2].token = XS_TOKEN_COALESCE_ASSIGN; |
1032 | 532 | fxGetNextCharacter(parser); |
1033 | 532 | } |
1034 | 2.16k | } |
1035 | 6.41k | else |
1036 | 6.41k | parser->states[2].token = XS_TOKEN_QUESTION_MARK; |
1037 | 14.3k | break; |
1038 | 571k | case '(': |
1039 | 571k | parser->states[2].token = XS_TOKEN_LEFT_PARENTHESIS; |
1040 | 571k | fxGetNextCharacter(parser); |
1041 | 571k | break; |
1042 | 459k | case ')': |
1043 | 459k | parser->states[2].token = XS_TOKEN_RIGHT_PARENTHESIS; |
1044 | 459k | fxGetNextCharacter(parser); |
1045 | 459k | break; |
1046 | 125k | case '[': |
1047 | 125k | parser->states[2].token = XS_TOKEN_LEFT_BRACKET; |
1048 | 125k | fxGetNextCharacter(parser); |
1049 | 125k | break; |
1050 | 120k | case ']': |
1051 | 120k | parser->states[2].token = XS_TOKEN_RIGHT_BRACKET; |
1052 | 120k | fxGetNextCharacter(parser); |
1053 | 120k | break; |
1054 | 406k | case '{': |
1055 | 406k | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1056 | 406k | fxGetNextCharacter(parser); |
1057 | 406k | break; |
1058 | 184k | case '}': |
1059 | 184k | parser->states[2].token = XS_TOKEN_RIGHT_BRACE; |
1060 | 184k | fxGetNextCharacter(parser); |
1061 | 184k | break; |
1062 | 156k | case '=': |
1063 | 156k | fxGetNextCharacter(parser); |
1064 | 156k | if (parser->character == '=') { |
1065 | 3.77k | fxGetNextCharacter(parser); |
1066 | 3.77k | if (parser->character == '=') { |
1067 | 2.38k | parser->states[2].token = XS_TOKEN_STRICT_EQUAL; |
1068 | 2.38k | fxGetNextCharacter(parser); |
1069 | 2.38k | } |
1070 | 1.38k | else |
1071 | 1.38k | parser->states[2].token = XS_TOKEN_EQUAL; |
1072 | 3.77k | } |
1073 | 152k | else if (parser->character == '>') { |
1074 | 29.7k | parser->states[2].token = XS_TOKEN_ARROW; |
1075 | 29.7k | fxGetNextCharacter(parser); |
1076 | 29.7k | } |
1077 | 122k | else |
1078 | 122k | parser->states[2].token = XS_TOKEN_ASSIGN; |
1079 | 156k | break; |
1080 | 39.9k | case '<': |
1081 | 39.9k | fxGetNextCharacter(parser); |
1082 | 39.9k | if (parser->character == '<') { |
1083 | 8.49k | fxGetNextCharacter(parser); |
1084 | 8.49k | if (parser->character == '=') { |
1085 | 1 | parser->states[2].token = XS_TOKEN_LEFT_SHIFT_ASSIGN; |
1086 | 1 | fxGetNextCharacter(parser); |
1087 | 1 | } |
1088 | 8.49k | else |
1089 | 8.49k | parser->states[2].token = XS_TOKEN_LEFT_SHIFT; |
1090 | 8.49k | } |
1091 | 31.4k | else if (parser->character == '=') { |
1092 | 1.57k | parser->states[2].token = XS_TOKEN_LESS_EQUAL; |
1093 | 1.57k | fxGetNextCharacter(parser); |
1094 | 1.57k | } |
1095 | 29.8k | else |
1096 | 29.8k | parser->states[2].token = XS_TOKEN_LESS; |
1097 | 39.9k | break; |
1098 | 57.6k | case '>': |
1099 | 57.6k | fxGetNextCharacter(parser); |
1100 | 57.6k | if (parser->character == '>') { |
1101 | 3.22k | fxGetNextCharacter(parser); |
1102 | 3.22k | if (parser->character == '>') { |
1103 | 1.38k | fxGetNextCharacter(parser); |
1104 | 1.38k | if (parser->character == '=') { |
1105 | 98 | parser->states[2].token = XS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGN; |
1106 | 98 | fxGetNextCharacter(parser); |
1107 | 98 | } |
1108 | 1.29k | else |
1109 | 1.29k | parser->states[2].token = XS_TOKEN_UNSIGNED_RIGHT_SHIFT; |
1110 | 1.38k | } |
1111 | 1.83k | else if (parser->character == '=') { |
1112 | 91 | parser->states[2].token = XS_TOKEN_SIGNED_RIGHT_SHIFT_ASSIGN; |
1113 | 91 | fxGetNextCharacter(parser); |
1114 | 91 | } |
1115 | 1.74k | else |
1116 | 1.74k | parser->states[2].token = XS_TOKEN_SIGNED_RIGHT_SHIFT; |
1117 | 3.22k | } |
1118 | 54.3k | else if (parser->character == '=') { |
1119 | 2.40k | parser->states[2].token = XS_TOKEN_MORE_EQUAL; |
1120 | 2.40k | fxGetNextCharacter(parser); |
1121 | 2.40k | } |
1122 | 51.9k | else |
1123 | 51.9k | parser->states[2].token = XS_TOKEN_MORE; |
1124 | 57.6k | break; |
1125 | 179k | case '!': |
1126 | 179k | fxGetNextCharacter(parser); |
1127 | 179k | if (parser->character == '=') { |
1128 | 4.84k | fxGetNextCharacter(parser); |
1129 | 4.84k | if (parser->character == '=') { |
1130 | 1.36k | parser->states[2].token = XS_TOKEN_STRICT_NOT_EQUAL; |
1131 | 1.36k | fxGetNextCharacter(parser); |
1132 | 1.36k | } |
1133 | 3.47k | else |
1134 | 3.47k | parser->states[2].token = XS_TOKEN_NOT_EQUAL; |
1135 | 4.84k | } |
1136 | 175k | else |
1137 | 175k | parser->states[2].token = XS_TOKEN_NOT; |
1138 | 179k | break; |
1139 | 2.97k | case '~': |
1140 | 2.97k | parser->states[2].token = XS_TOKEN_BIT_NOT; |
1141 | 2.97k | fxGetNextCharacter(parser); |
1142 | 2.97k | break; |
1143 | 21.4k | case '&': |
1144 | 21.4k | fxGetNextCharacter(parser); |
1145 | 21.4k | if (parser->character == '=') { |
1146 | 1.33k | parser->states[2].token = XS_TOKEN_BIT_AND_ASSIGN; |
1147 | 1.33k | fxGetNextCharacter(parser); |
1148 | 1.33k | } |
1149 | 20.1k | else if (parser->character == '&') { |
1150 | 10.0k | parser->states[2].token = XS_TOKEN_AND; |
1151 | 10.0k | fxGetNextCharacter(parser); |
1152 | 10.0k | if (parser->character == '=') { |
1153 | 4.20k | parser->states[2].token = XS_TOKEN_AND_ASSIGN; |
1154 | 4.20k | fxGetNextCharacter(parser); |
1155 | 4.20k | } |
1156 | 10.0k | } |
1157 | 10.0k | else |
1158 | 10.0k | parser->states[2].token = XS_TOKEN_BIT_AND; |
1159 | 21.4k | break; |
1160 | 12.8k | case '|': |
1161 | 12.8k | fxGetNextCharacter(parser); |
1162 | 12.8k | if (parser->character == '=') { |
1163 | 116 | parser->states[2].token = XS_TOKEN_BIT_OR_ASSIGN; |
1164 | 116 | fxGetNextCharacter(parser); |
1165 | 116 | } |
1166 | 12.7k | else if (parser->character == '|') { |
1167 | 3.82k | parser->states[2].token = XS_TOKEN_OR; |
1168 | 3.82k | fxGetNextCharacter(parser); |
1169 | 3.82k | if (parser->character == '=') { |
1170 | 207 | parser->states[2].token = XS_TOKEN_OR_ASSIGN; |
1171 | 207 | fxGetNextCharacter(parser); |
1172 | 207 | } |
1173 | 3.82k | } |
1174 | 8.91k | else |
1175 | 8.91k | parser->states[2].token = XS_TOKEN_BIT_OR; |
1176 | 12.8k | break; |
1177 | 6.72k | case '^': |
1178 | 6.72k | fxGetNextCharacter(parser); |
1179 | 6.72k | if (parser->character == '=') { |
1180 | 2.07k | parser->states[2].token = XS_TOKEN_BIT_XOR_ASSIGN; |
1181 | 2.07k | fxGetNextCharacter(parser); |
1182 | 2.07k | } |
1183 | 4.64k | else |
1184 | 4.64k | parser->states[2].token = XS_TOKEN_BIT_XOR; |
1185 | 6.72k | break; |
1186 | 39.5k | case '+': |
1187 | 39.5k | fxGetNextCharacter(parser); |
1188 | 39.5k | if (parser->character == '=') { |
1189 | 1.87k | parser->states[2].token = XS_TOKEN_ADD_ASSIGN; |
1190 | 1.87k | fxGetNextCharacter(parser); |
1191 | 1.87k | } |
1192 | 37.6k | else if (parser->character == '+') { |
1193 | 12.8k | parser->states[2].token = XS_TOKEN_INCREMENT; |
1194 | 12.8k | fxGetNextCharacter(parser); |
1195 | 12.8k | } |
1196 | 24.8k | else |
1197 | 24.8k | parser->states[2].token = XS_TOKEN_ADD; |
1198 | 39.5k | break; |
1199 | 4.75M | case '-': |
1200 | 4.75M | fxGetNextCharacter(parser); |
1201 | 4.75M | if (parser->character == '=') { |
1202 | 4.06k | parser->states[2].token = XS_TOKEN_SUBTRACT_ASSIGN; |
1203 | 4.06k | fxGetNextCharacter(parser); |
1204 | 4.06k | } |
1205 | 4.74M | else if (parser->character == '-') { |
1206 | 210k | parser->states[2].token = XS_TOKEN_DECREMENT; |
1207 | 210k | fxGetNextCharacter(parser); |
1208 | 210k | } |
1209 | 4.53M | else |
1210 | 4.53M | parser->states[2].token = XS_TOKEN_SUBTRACT; |
1211 | 4.75M | break; |
1212 | 17.9k | case '*': |
1213 | 17.9k | fxGetNextCharacter(parser); |
1214 | 17.9k | if (parser->character == '=') { |
1215 | 188 | parser->states[2].token = XS_TOKEN_MULTIPLY_ASSIGN; |
1216 | 188 | fxGetNextCharacter(parser); |
1217 | 188 | } |
1218 | 17.7k | else if (parser->character == '*') { |
1219 | 1.56k | fxGetNextCharacter(parser); |
1220 | 1.56k | if (parser->character == '=') { |
1221 | 7 | parser->states[2].token = XS_TOKEN_EXPONENTIATION_ASSIGN; |
1222 | 7 | fxGetNextCharacter(parser); |
1223 | 7 | } |
1224 | 1.56k | else |
1225 | 1.56k | parser->states[2].token = XS_TOKEN_EXPONENTIATION; |
1226 | 1.56k | } |
1227 | 16.1k | else |
1228 | 16.1k | parser->states[2].token = XS_TOKEN_MULTIPLY; |
1229 | 17.9k | break; |
1230 | 307k | case '/': |
1231 | 307k | fxGetNextCharacter(parser); |
1232 | 307k | if (parser->character == '*') { |
1233 | 10.5k | fxGetNextCharacter(parser); |
1234 | 2.68M | for (;;) { |
1235 | 2.68M | if (parser->character == (txU4)C_EOF) { |
1236 | 1.57k | fxReportParserError(parser, parser->states[2].line, "end of file in comment"); |
1237 | 1.57k | break; |
1238 | 1.57k | } |
1239 | 2.68M | else if ((parser->character == 10) || (parser->character == 0x2028) || (parser->character == 0x2029)) { |
1240 | 40.1k | parser->states[2].line++; |
1241 | 40.1k | fxGetNextCharacter(parser); |
1242 | 40.1k | parser->states[2].crlf = 1; |
1243 | 40.1k | } |
1244 | 2.64M | else if (parser->character == 13) { |
1245 | 15.9k | parser->states[2].line++; |
1246 | 15.9k | fxGetNextCharacter(parser); |
1247 | 15.9k | if (parser->character == 10) |
1248 | 2.78k | fxGetNextCharacter(parser); |
1249 | 15.9k | parser->states[2].crlf = 1; |
1250 | 15.9k | } |
1251 | 2.63M | else if (parser->character == '*') { |
1252 | 13.2k | fxGetNextCharacter(parser); |
1253 | 13.2k | if (parser->character == '/') { |
1254 | 8.97k | fxGetNextCharacter(parser); |
1255 | 8.97k | break; |
1256 | 8.97k | } |
1257 | 13.2k | } |
1258 | 2.61M | else |
1259 | 2.61M | fxGetNextCharacter(parser); |
1260 | 2.68M | } |
1261 | 10.5k | } |
1262 | 297k | else if (parser->character == '/') { |
1263 | 214k | fxGetNextCharacter(parser); |
1264 | 214k | p = parser->buffer; |
1265 | 214k | q = p + parser->bufferSize - 1; |
1266 | 15.0M | while ((parser->character != (txU4)C_EOF) && (parser->character != 10) && (parser->character != 13) && (parser->character != 0x2028) && (parser->character != 0x2029)) { |
1267 | 14.8M | if (p < q) |
1268 | 14.7M | *p++ = (char)parser->character; |
1269 | 14.8M | fxGetNextCharacter(parser); |
1270 | 14.8M | } |
1271 | 214k | *p = 0; |
1272 | 214k | p = parser->buffer; |
1273 | 214k | if ((*p == '#') || (*p == '@')) { |
1274 | 28.7k | if (!c_strncmp(p, "@line ", 6)) { |
1275 | 10.5k | p += 6; |
1276 | 10.5k | t = 0; |
1277 | 10.5k | c = *p++; |
1278 | 98.3k | while (('0' <= c) && (c <= '9')) { |
1279 | 87.8k | t = (t * 10) + (c - '0'); |
1280 | 87.8k | c = *p++; |
1281 | 87.8k | } |
1282 | 10.5k | if (!t) goto bail; |
1283 | 9.67k | if (c == ' ') { |
1284 | 1.37k | c = *p++; |
1285 | 1.37k | if (c != '"') goto bail; |
1286 | 825 | q = p; |
1287 | 825 | c = *q++; |
1288 | 18.0k | while ((c != 0) && (c != 10) && (c != 13) && (c != '"')) |
1289 | 17.2k | c = *q++; |
1290 | 825 | if (c != '"') goto bail; |
1291 | 180 | *(--q) = 0; |
1292 | 180 | parser->path = fxNewParserSymbol(parser, p); |
1293 | 180 | } |
1294 | 8.48k | parser->states[2].line = t - 1; |
1295 | 8.48k | } |
1296 | 18.2k | else if (!c_strncmp(p, "# sourceMappingURL=", 19) || !c_strncmp(p, "@ sourceMappingURL=", 19)) { |
1297 | 117 | p += 19; |
1298 | 117 | q = p; |
1299 | 878 | while (((c = *q)) && (c != 10) && (c != 13)) |
1300 | 761 | q++; |
1301 | 117 | *q = 0; |
1302 | 117 | parser->name = fxNewParserString(parser, p, mxPtrDiff(q - p)); |
1303 | 117 | } |
1304 | 18.1k | else if (!c_strncmp(p, "# sourceURL=", 12) || !c_strncmp(p, "@ sourceURL=", 12)) { |
1305 | 418 | p += 12; |
1306 | 418 | q = p; |
1307 | 131k | while (((c = *q)) && (c != 10) && (c != 13)) |
1308 | 131k | q++; |
1309 | 418 | *q = 0; |
1310 | 418 | parser->source = fxNewParserSymbol(parser, p); |
1311 | 418 | } |
1312 | 28.7k | } |
1313 | 214k | bail: |
1314 | 214k | ; |
1315 | 214k | } |
1316 | 82.5k | else if (parser->character == '=') { |
1317 | 1.10k | parser->states[2].token = XS_TOKEN_DIVIDE_ASSIGN; |
1318 | 1.10k | fxGetNextCharacter(parser); |
1319 | 1.10k | } |
1320 | 81.4k | else |
1321 | 81.4k | parser->states[2].token = XS_TOKEN_DIVIDE; |
1322 | 307k | break; |
1323 | 307k | case '%': |
1324 | 7.61k | fxGetNextCharacter(parser); |
1325 | 7.61k | if (parser->character == '=') { |
1326 | 129 | parser->states[2].token = XS_TOKEN_MODULO_ASSIGN; |
1327 | 129 | fxGetNextCharacter(parser); |
1328 | 129 | } |
1329 | 7.48k | else |
1330 | 7.48k | parser->states[2].token = XS_TOKEN_MODULO; |
1331 | 7.61k | break; |
1332 | | |
1333 | 130k | case '"': |
1334 | 195k | case '\'': |
1335 | 195k | c = parser->character; |
1336 | 195k | fxGetNextCharacter(parser); |
1337 | 195k | fxGetNextString(parser, c); |
1338 | 195k | parser->states[2].token = XS_TOKEN_STRING; |
1339 | 195k | fxGetNextCharacter(parser); |
1340 | 195k | break; |
1341 | | |
1342 | 250k | case '`': |
1343 | 250k | fxGetNextCharacter(parser); |
1344 | 250k | fxGetNextString(parser, '`'); |
1345 | 250k | if (parser->character == '{') |
1346 | 1.78k | parser->states[2].token = XS_TOKEN_TEMPLATE_HEAD; |
1347 | 248k | else |
1348 | 248k | parser->states[2].token = XS_TOKEN_TEMPLATE; |
1349 | 250k | fxGetNextCharacter(parser); |
1350 | 250k | break; |
1351 | | |
1352 | 1.34k | case '@': |
1353 | 1.34k | if (parser->flags & mxCFlag) |
1354 | 0 | parser->states[2].token = XS_TOKEN_HOST; |
1355 | 1.34k | else |
1356 | 1.34k | fxReportParserError(parser, parser->states[2].line, "invalid character @"); |
1357 | 1.34k | fxGetNextCharacter(parser); |
1358 | 1.34k | break; |
1359 | | |
1360 | 2.23M | default: |
1361 | 2.23M | p = parser->buffer; |
1362 | 2.23M | q = p + parser->bufferSize - 1; |
1363 | 2.23M | if (parser->character == '#') { |
1364 | 17.0k | *p++ = '#'; |
1365 | 17.0k | fxGetNextCharacter(parser); |
1366 | 17.0k | } |
1367 | 2.23M | if (fxIsIdentifierFirst(parser->character)) { |
1368 | 2.16M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1369 | 2.16M | fxGetNextCharacter(parser); |
1370 | 2.16M | } |
1371 | 65.9k | else if (parser->character == '\\') { |
1372 | 2.15k | parser->states[2].escaped = 1; |
1373 | 2.15k | t = 0; |
1374 | 2.15k | if (fxGetNextIdentiferX(parser, &t) && fxIsIdentifierFirst(t)) |
1375 | 499 | p = fxUTF8Buffer(parser, t, p, q); |
1376 | 1.65k | else |
1377 | 1.65k | p = C_NULL; |
1378 | 2.15k | } |
1379 | 63.8k | else |
1380 | 63.8k | p = C_NULL; |
1381 | 2.23M | if (p) { |
1382 | 13.7M | for (;;) { |
1383 | 13.7M | if (p == q) { |
1384 | 1 | fxReportMemoryError(parser, parser->states[2].line, "identifier overflow"); |
1385 | 1 | } |
1386 | 13.7M | if (fxIsIdentifierNext(parser->character)) { |
1387 | 11.5M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1388 | 11.5M | fxGetNextCharacter(parser); |
1389 | 11.5M | } |
1390 | 2.16M | else if (parser->character == '\\') { |
1391 | 1.02k | parser->states[2].escaped = 1; |
1392 | 1.02k | t = 0; |
1393 | 1.02k | if (fxGetNextIdentiferX(parser, &t) && fxIsIdentifierNext(t)) |
1394 | 256 | p = fxUTF8Buffer(parser, t, p, q); |
1395 | 772 | else { |
1396 | 772 | p = C_NULL; |
1397 | 772 | break; |
1398 | 772 | } |
1399 | 1.02k | } |
1400 | 2.16M | else { |
1401 | 2.16M | *p = 0; |
1402 | 2.16M | if (parser->buffer[0] == '#') { |
1403 | 15.6k | parser->states[2].symbol = fxNewParserSymbol(parser, parser->buffer); |
1404 | 15.6k | parser->states[2].token = XS_TOKEN_PRIVATE_IDENTIFIER; |
1405 | 15.6k | } |
1406 | 2.15M | else { |
1407 | 2.15M | fxGetNextKeyword(parser); |
1408 | 2.15M | } |
1409 | 2.16M | break; |
1410 | 2.16M | } |
1411 | 13.7M | } |
1412 | 2.16M | } |
1413 | 2.23M | if (!p) { |
1414 | 66.2k | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1415 | 66.2k | fxGetNextCharacter(parser); |
1416 | 66.2k | } |
1417 | 2.23M | break; |
1418 | 19.6M | } |
1419 | 19.6M | } |
1420 | 16.1M | } |
1421 | | |
1422 | | void fxGetNextTokenTemplate(txParser* parser) |
1423 | 6.93k | { |
1424 | 6.93k | parser->states[2].crlf = 0; |
1425 | 6.93k | parser->states[2].escaped = 0; |
1426 | 6.93k | parser->states[2].integer = 0; |
1427 | 6.93k | parser->states[2].modifierLength = 0; |
1428 | 6.93k | parser->states[2].modifier = parser->emptyString; |
1429 | 6.93k | parser->states[2].number = 0; |
1430 | 6.93k | parser->states[2].rawLength = 0; |
1431 | 6.93k | parser->states[2].raw = parser->emptyString; |
1432 | 6.93k | parser->states[2].stringLength = 0; |
1433 | 6.93k | parser->states[2].string = parser->emptyString; |
1434 | 6.93k | parser->states[2].symbol = C_NULL; |
1435 | 6.93k | parser->states[2].token = XS_NO_TOKEN; |
1436 | 6.93k | fxGetNextString(parser, '`'); |
1437 | 6.93k | if (parser->character == '{') |
1438 | 5.16k | parser->states[2].token = XS_TOKEN_TEMPLATE_MIDDLE; |
1439 | 1.76k | else |
1440 | 1.76k | parser->states[2].token = XS_TOKEN_TEMPLATE_TAIL; |
1441 | 6.93k | fxGetNextCharacter(parser); |
1442 | 6.93k | parser->states[0] = parser->states[2]; |
1443 | 6.93k | parser->ahead = 0; |
1444 | 6.93k | } |
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 | 45.1k | #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 | 361k | { |
1648 | 361k | return c_strcmp((char*)name, ((txEntity*)entity)->name); |
1649 | 361k | } |
1650 | | |
1651 | | txString fxGetNextEntity(txParser* parser, txString p, txString q) |
1652 | 48.9k | { |
1653 | 48.9k | txString r = p; |
1654 | 48.9k | txU4 t = 0; |
1655 | 48.9k | if (p < q) *p++ = '&'; |
1656 | 48.9k | fxGetNextCharacter(parser); |
1657 | 48.9k | if (parser->character == '#') { |
1658 | 3.70k | if (p < q) *p++ = '#'; |
1659 | 3.70k | fxGetNextCharacter(parser); |
1660 | 3.70k | if (parser->character == 'x') { |
1661 | 2.59k | if (p < q) *p++ = 'x'; |
1662 | 2.59k | fxGetNextCharacter(parser); |
1663 | 13.4k | while (fxGetNextStringX(parser->character, &t)) { |
1664 | 10.8k | if (p < q) *p++ = parser->character; |
1665 | 10.8k | fxGetNextCharacter(parser); |
1666 | 10.8k | } |
1667 | 2.59k | } |
1668 | 1.10k | else { |
1669 | 2.33k | while (fxGetNextStringD(parser->character, &t)) { |
1670 | 1.22k | if (p < q) *p++ = parser->character; |
1671 | 1.22k | fxGetNextCharacter(parser); |
1672 | 1.22k | } |
1673 | 1.10k | } |
1674 | 3.70k | } |
1675 | 45.2k | else { |
1676 | 45.2k | txEntity* entity = C_NULL; |
1677 | 45.2k | int c = parser->character; |
1678 | 58.8k | while ((p < q) && ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z')))) { |
1679 | 13.6k | if (p < q) *p++ = c; |
1680 | 13.6k | fxGetNextCharacter(parser); |
1681 | 13.6k | c = parser->character; |
1682 | 13.6k | } |
1683 | 45.2k | *p = 0; |
1684 | 45.2k | if (r < q) |
1685 | 45.1k | entity = (txEntity*)c_bsearch(r + 1, gxEntities, XS_ENTITIES_COUNT, sizeof(txEntity), fxCompareEntities); |
1686 | 45.2k | t = entity ? entity->value : 0; |
1687 | 45.2k | } |
1688 | 48.9k | if (parser->character == ';') { |
1689 | 2.54k | if (p < q) *p++ = ';'; |
1690 | 2.54k | fxGetNextCharacter(parser); |
1691 | 2.54k | if (t) |
1692 | 2.29k | p = fxUTF8Buffer(parser, t, r, q); |
1693 | 2.54k | } |
1694 | 48.9k | return p; |
1695 | 48.9k | } |
1696 | | |
1697 | | void fxGetNextTokenJSXAttribute(txParser* parser) |
1698 | 1.97k | { |
1699 | 1.97k | txString p = parser->buffer; |
1700 | 1.97k | txString q = p + parser->bufferSize - 1; |
1701 | 1.97k | txU4 quote = 0; |
1702 | 1.97k | parser->states[2].crlf = 0; |
1703 | 1.97k | parser->states[2].escaped = 0; |
1704 | 1.97k | parser->states[2].integer = 0; |
1705 | 1.97k | parser->states[2].modifierLength = 0; |
1706 | 1.97k | parser->states[2].modifier = parser->emptyString; |
1707 | 1.97k | parser->states[2].number = 0; |
1708 | 1.97k | parser->states[2].rawLength = 0; |
1709 | 1.97k | parser->states[2].raw = parser->emptyString; |
1710 | 1.97k | parser->states[2].stringLength = 0; |
1711 | 1.97k | parser->states[2].string = parser->emptyString; |
1712 | 1.97k | parser->states[2].symbol = C_NULL; |
1713 | 1.97k | parser->states[2].token = XS_NO_TOKEN; |
1714 | 1.44M | while (parser->states[2].token == XS_NO_TOKEN) { |
1715 | 1.44M | switch (parser->character) { |
1716 | 785 | case C_EOF: |
1717 | 785 | parser->states[2].token = XS_TOKEN_EOF; |
1718 | 785 | break; |
1719 | 18.8k | case 10: |
1720 | 18.9k | case 0x2028: // <LS> |
1721 | 19.2k | case 0x2029: // <PS> |
1722 | 19.2k | parser->states[2].line++; |
1723 | 19.2k | if (quote) |
1724 | 12.7k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1725 | 19.2k | fxGetNextCharacter(parser); |
1726 | 19.2k | parser->states[2].crlf = 1; |
1727 | 19.2k | break; |
1728 | 111k | case 13: |
1729 | 111k | parser->states[2].line++; |
1730 | 111k | if (quote) |
1731 | 111k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1732 | 111k | fxGetNextCharacter(parser); |
1733 | 111k | if (parser->character == 10) { |
1734 | 998 | if (quote) |
1735 | 916 | p = fxUTF8Buffer(parser, parser->character, p, q); |
1736 | 998 | fxGetNextCharacter(parser); |
1737 | 998 | } |
1738 | 111k | parser->states[2].crlf = 1; |
1739 | 111k | break; |
1740 | 919 | case '\t': |
1741 | 1.17k | case 11: |
1742 | 2.00k | case 12: |
1743 | 43.6k | case ' ': |
1744 | 43.7k | case 0x00A0: |
1745 | 44.0k | case 0x1680: |
1746 | 44.0k | case 0x2000: |
1747 | 44.3k | case 0x2001: |
1748 | 44.3k | case 0x2002: |
1749 | 45.0k | case 0x2003: |
1750 | 45.0k | case 0x2004: |
1751 | 45.6k | case 0x2005: |
1752 | 45.7k | case 0x2006: |
1753 | 45.7k | case 0x2007: |
1754 | 45.7k | case 0x2008: |
1755 | 45.8k | case 0x2009: |
1756 | 46.5k | case 0x200A: |
1757 | 46.6k | case 0x202F: |
1758 | 46.6k | case 0x205F: |
1759 | 46.6k | case 0x3000: |
1760 | 46.7k | case 0xFEFF: |
1761 | 46.7k | if (quote) |
1762 | 46.5k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1763 | 46.7k | fxGetNextCharacter(parser); |
1764 | 46.7k | break; |
1765 | | |
1766 | 9.26k | case '{': |
1767 | 9.26k | if (quote) |
1768 | 9.25k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1769 | 14 | else |
1770 | 14 | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1771 | 9.26k | fxGetNextCharacter(parser); |
1772 | 9.26k | break; |
1773 | | |
1774 | 1.51k | case '"': |
1775 | 61.5k | case '\'': |
1776 | 61.5k | if (quote) { |
1777 | 59.6k | if (quote == parser->character) { |
1778 | 1.02k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
1779 | 1.02k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
1780 | 1.02k | parser->states[2].token = XS_TOKEN_STRING; |
1781 | 1.02k | } |
1782 | 58.6k | else |
1783 | 58.6k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1784 | 59.6k | } |
1785 | 1.82k | else |
1786 | 1.82k | quote = parser->character; |
1787 | 61.5k | fxGetNextCharacter(parser); |
1788 | 61.5k | break; |
1789 | | |
1790 | 47.4k | case '&': |
1791 | 47.4k | if (quote) |
1792 | 47.4k | 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 | 47.4k | break; |
1798 | | |
1799 | 1.14M | default: |
1800 | 1.14M | if (quote) |
1801 | 1.14M | p = fxUTF8Buffer(parser, parser->character, p, q); |
1802 | 123 | else |
1803 | 123 | fxReportParserError(parser, parser->states[2].line, "invalid character %d", parser->character); |
1804 | 1.14M | fxGetNextCharacter(parser); |
1805 | 1.14M | break; |
1806 | 1.44M | } |
1807 | 1.44M | } |
1808 | 1.82k | parser->states[0] = parser->states[2]; |
1809 | 1.82k | parser->ahead = 0; |
1810 | 1.82k | } |
1811 | | |
1812 | | void fxGetNextTokenJSXChild(txParser* parser) |
1813 | 33.2k | { |
1814 | 33.2k | txString p = parser->buffer; |
1815 | 33.2k | txString q = p + parser->bufferSize - 1; |
1816 | 33.2k | txString s = C_NULL; |
1817 | 33.2k | char c; |
1818 | 33.2k | txString after = C_NULL; |
1819 | 33.2k | txString before = C_NULL; |
1820 | 33.2k | txString text = C_NULL; |
1821 | 33.2k | parser->states[2].crlf = 0; |
1822 | 33.2k | parser->states[2].escaped = 0; |
1823 | 33.2k | parser->states[2].integer = 0; |
1824 | 33.2k | parser->states[2].modifierLength = 0; |
1825 | 33.2k | parser->states[2].modifier = parser->emptyString; |
1826 | 33.2k | parser->states[2].number = 0; |
1827 | 33.2k | parser->states[2].rawLength = 0; |
1828 | 33.2k | parser->states[2].raw = parser->emptyString; |
1829 | 33.2k | parser->states[2].stringLength = 0; |
1830 | 33.2k | parser->states[2].string = parser->emptyString; |
1831 | 33.2k | parser->states[2].symbol = C_NULL; |
1832 | 33.2k | parser->states[2].token = XS_NO_TOKEN; |
1833 | 590k | while (parser->states[2].token == XS_NO_TOKEN) { |
1834 | 557k | switch (parser->character) { |
1835 | 214 | case C_EOF: |
1836 | 214 | parser->states[2].token = XS_TOKEN_EOF; |
1837 | 214 | break; |
1838 | 6.63k | case 10: |
1839 | 6.73k | case 0x2028: // <LS> |
1840 | 6.80k | case 0x2029: // <PS> |
1841 | 6.80k | parser->states[2].line++; |
1842 | 6.80k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1843 | 6.80k | fxGetNextCharacter(parser); |
1844 | 6.80k | parser->states[2].crlf = 1; |
1845 | 6.80k | break; |
1846 | 6.80k | case 13: |
1847 | 6.80k | parser->states[2].line++; |
1848 | 6.80k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1849 | 6.80k | fxGetNextCharacter(parser); |
1850 | 6.80k | if (parser->character == 10) { |
1851 | 6.01k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1852 | 6.01k | fxGetNextCharacter(parser); |
1853 | 6.01k | } |
1854 | 6.80k | parser->states[2].crlf = 1; |
1855 | 6.80k | break; |
1856 | | |
1857 | 28.3k | case '<': |
1858 | 28.3k | fxGetNextCharacter(parser); |
1859 | 28.3k | parser->states[2].token = XS_TOKEN_LESS; |
1860 | 28.3k | break; |
1861 | 1.05k | case '>': |
1862 | 1.05k | fxGetNextCharacter(parser); |
1863 | 1.05k | parser->states[2].token = XS_TOKEN_MORE; |
1864 | 1.05k | break; |
1865 | 3.03k | case '{': |
1866 | 3.03k | fxGetNextCharacter(parser); |
1867 | 3.03k | parser->states[2].token = XS_TOKEN_LEFT_BRACE; |
1868 | 3.03k | break; |
1869 | 540 | case '}': |
1870 | 540 | fxGetNextCharacter(parser); |
1871 | 540 | parser->states[2].token = XS_TOKEN_RIGHT_BRACE; |
1872 | 540 | break; |
1873 | 1.51k | case '&': |
1874 | 1.51k | p = fxGetNextEntity(parser, p, q); |
1875 | 1.51k | break; |
1876 | 509k | default: |
1877 | 509k | p = fxUTF8Buffer(parser, parser->character, p, q); |
1878 | 509k | fxGetNextCharacter(parser); |
1879 | 509k | break; |
1880 | 557k | } |
1881 | 557k | } |
1882 | 33.2k | parser->states[2].rawLength = mxPtrDiff(p - parser->buffer); |
1883 | 33.2k | parser->states[2].raw = fxNewParserString(parser, parser->buffer, parser->states[2].rawLength); |
1884 | 33.2k | if (parser->states[2].crlf) { |
1885 | 2.45k | p = parser->buffer; |
1886 | 2.45k | q = p + parser->bufferSize - 1; |
1887 | 2.45k | s = parser->states[2].raw; |
1888 | 2.45k | c = *s++; |
1889 | 588k | while (c) { |
1890 | 586k | if ((c == 10) || (c == 13)) { |
1891 | 7.66k | if (before) |
1892 | 2.52k | p = before; |
1893 | 5.13k | else |
1894 | 5.13k | before = p; |
1895 | 7.66k | after = p; |
1896 | 7.66k | } |
1897 | 578k | else if ((c == 9) || (c == 32)) { |
1898 | 19.7k | if (!before) |
1899 | 13.5k | before = p; |
1900 | 19.7k | *p++ = c; |
1901 | 19.7k | } |
1902 | 558k | else { |
1903 | 558k | if (after) { |
1904 | 5.11k | p = after; |
1905 | 5.11k | if (text) |
1906 | 4.28k | *p++ = 32; |
1907 | 5.11k | } |
1908 | 558k | after = C_NULL; |
1909 | 558k | before = C_NULL; |
1910 | 558k | text = p; |
1911 | 558k | *p++ = c; |
1912 | 558k | } |
1913 | 586k | c = *s++; |
1914 | 586k | } |
1915 | 2.45k | if (after) |
1916 | 602 | p = after; |
1917 | 2.45k | } |
1918 | 33.2k | parser->states[2].stringLength = mxPtrDiff(p - parser->buffer); |
1919 | 33.2k | parser->states[2].string = fxNewParserString(parser, parser->buffer, parser->states[2].stringLength); |
1920 | | |
1921 | 33.2k | parser->states[0] = parser->states[2]; |
1922 | 33.2k | parser->ahead = 0; |
1923 | 33.2k | } |
1924 | | |
1925 | | |
1926 | | |
1927 | | |
1928 | | |
1929 | | |
1930 | | |
1931 | | |
1932 | | |
1933 | | |
1934 | | |
1935 | | |
1936 | | |
1937 | | |
1938 | | |
1939 | | |