Coverage Report

Created: 2026-07-16 06:43

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