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