Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7641 views
1
#include "jsi.h"
2
#include "jslex.h"
3
#include "jsparse.h"
4
5
#define LIST(h) jsP_newnode(J, AST_LIST, h, 0, 0, 0)
6
7
#define EXP0(x) jsP_newnode(J, EXP_ ## x, 0, 0, 0, 0)
8
#define EXP1(x,a) jsP_newnode(J, EXP_ ## x, a, 0, 0, 0)
9
#define EXP2(x,a,b) jsP_newnode(J, EXP_ ## x, a, b, 0, 0)
10
#define EXP3(x,a,b,c) jsP_newnode(J, EXP_ ## x, a, b, c, 0)
11
12
#define STM0(x) jsP_newnode(J, STM_ ## x, 0, 0, 0, 0)
13
#define STM1(x,a) jsP_newnode(J, STM_ ## x, a, 0, 0, 0)
14
#define STM2(x,a,b) jsP_newnode(J, STM_ ## x, a, b, 0, 0)
15
#define STM3(x,a,b,c) jsP_newnode(J, STM_ ## x, a, b, c, 0)
16
#define STM4(x,a,b,c,d) jsP_newnode(J, STM_ ## x, a, b, c, d)
17
18
static js_Ast *expression(js_State *J, int notin);
19
static js_Ast *assignment(js_State *J, int notin);
20
static js_Ast *memberexp(js_State *J);
21
static js_Ast *statement(js_State *J);
22
static js_Ast *funbody(js_State *J);
23
24
JS_NORETURN static void jsP_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
25
26
static void jsP_error(js_State *J, const char *fmt, ...)
27
{
28
va_list ap;
29
char buf[512];
30
char msgbuf[256];
31
32
va_start(ap, fmt);
33
vsnprintf(msgbuf, 256, fmt, ap);
34
va_end(ap);
35
36
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
37
strcat(buf, msgbuf);
38
39
js_newsyntaxerror(J, buf);
40
js_throw(J);
41
}
42
43
static void jsP_warning(js_State *J, const char *fmt, ...)
44
{
45
va_list ap;
46
fprintf(stderr, "%s:%d: warning: ", J->filename, J->lexline);
47
va_start(ap, fmt);
48
vfprintf(stderr, fmt, ap);
49
va_end(ap);
50
fprintf(stderr, "\n");
51
}
52
53
static js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d)
54
{
55
js_Ast *node = js_malloc(J, sizeof *node);
56
57
node->type = type;
58
node->line = J->astline;
59
node->a = a;
60
node->b = b;
61
node->c = c;
62
node->d = d;
63
node->number = 0;
64
node->string = NULL;
65
node->jumps = NULL;
66
node->casejump = 0;
67
68
node->parent = NULL;
69
if (a) a->parent = node;
70
if (b) b->parent = node;
71
if (c) c->parent = node;
72
if (d) d->parent = node;
73
74
node->gcnext = J->gcast;
75
J->gcast = node;
76
77
return node;
78
}
79
80
static js_Ast *jsP_list(js_Ast *head)
81
{
82
/* set parent pointers in list nodes */
83
js_Ast *prev = head, *node = head->b;
84
while (node) {
85
node->parent = prev;
86
prev = node;
87
node = node->b;
88
}
89
return head;
90
}
91
92
static js_Ast *jsP_newstrnode(js_State *J, int type, const char *s)
93
{
94
js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0);
95
node->string = s;
96
return node;
97
}
98
99
static js_Ast *jsP_newnumnode(js_State *J, int type, double n)
100
{
101
js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0);
102
node->number = n;
103
return node;
104
}
105
106
static void jsP_freejumps(js_State *J, js_JumpList *node)
107
{
108
while (node) {
109
js_JumpList *next = node->next;
110
js_free(J, node);
111
node = next;
112
}
113
}
114
115
void jsP_freeparse(js_State *J)
116
{
117
js_Ast *node = J->gcast;
118
while (node) {
119
js_Ast *next = node->gcnext;
120
jsP_freejumps(J, node->jumps);
121
js_free(J, node);
122
node = next;
123
}
124
J->gcast = NULL;
125
}
126
127
/* Lookahead */
128
129
static void jsP_next(js_State *J)
130
{
131
J->astline = J->lexline;
132
J->lookahead = jsY_lex(J);
133
}
134
135
#define jsP_accept(J,x) (J->lookahead == x ? (jsP_next(J), 1) : 0)
136
137
#define jsP_expect(J,x) if (!jsP_accept(J, x)) jsP_error(J, "unexpected token: %s (expected %s)", jsY_tokenstring(J->lookahead), jsY_tokenstring(x))
138
139
static void semicolon(js_State *J)
140
{
141
if (J->lookahead == ';') {
142
jsP_next(J);
143
return;
144
}
145
if (J->newline || J->lookahead == '}' || J->lookahead == 0)
146
return;
147
jsP_error(J, "unexpected token: %s (expected ';')", jsY_tokenstring(J->lookahead));
148
}
149
150
/* Literals */
151
152
static const char *futurewords[] = {
153
"class", "const", "enum", "export", "extends", "import", "super",
154
};
155
156
static const char *strictfuturewords[] = {
157
"implements", "interface", "let", "package", "private", "protected",
158
"public", "static", "yield",
159
};
160
161
static void checkfutureword(js_State *J, const char *s)
162
{
163
if (jsY_findword(s, futurewords, nelem(futurewords)) >= 0)
164
jsP_error(J, "'%s' is a future reserved word", s);
165
if (J->strict && jsY_findword(s, strictfuturewords, nelem(strictfuturewords)) >= 0)
166
jsP_error(J, "'%s' is a strict mode future reserved word", s);
167
}
168
169
static js_Ast *identifier(js_State *J)
170
{
171
js_Ast *a;
172
if (J->lookahead == TK_IDENTIFIER) {
173
checkfutureword(J, J->text);
174
a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);
175
jsP_next(J);
176
return a;
177
}
178
jsP_error(J, "unexpected token: %s (expected identifier)", jsY_tokenstring(J->lookahead));
179
}
180
181
static js_Ast *identifieropt(js_State *J)
182
{
183
if (J->lookahead == TK_IDENTIFIER)
184
return identifier(J);
185
return NULL;
186
}
187
188
static js_Ast *identifiername(js_State *J)
189
{
190
if (J->lookahead == TK_IDENTIFIER || J->lookahead >= TK_BREAK) {
191
js_Ast *a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);
192
jsP_next(J);
193
return a;
194
}
195
jsP_error(J, "unexpected token: %s (expected identifier or keyword)", jsY_tokenstring(J->lookahead));
196
}
197
198
static js_Ast *arrayelement(js_State *J)
199
{
200
if (J->lookahead == ',')
201
return EXP0(UNDEF);
202
return assignment(J, 0);
203
}
204
205
static js_Ast *arrayliteral(js_State *J)
206
{
207
js_Ast *head, *tail;
208
if (J->lookahead == ']')
209
return NULL;
210
head = tail = LIST(arrayelement(J));
211
while (jsP_accept(J, ',')) {
212
if (J->lookahead != ']')
213
tail = tail->b = LIST(arrayelement(J));
214
}
215
return jsP_list(head);
216
}
217
218
static js_Ast *propname(js_State *J)
219
{
220
js_Ast *name;
221
if (J->lookahead == TK_NUMBER) {
222
name = jsP_newnumnode(J, EXP_NUMBER, J->number);
223
jsP_next(J);
224
} else if (J->lookahead == TK_STRING) {
225
name = jsP_newstrnode(J, EXP_STRING, J->text);
226
jsP_next(J);
227
} else {
228
name = identifiername(J);
229
}
230
return name;
231
}
232
233
static js_Ast *propassign(js_State *J)
234
{
235
js_Ast *name, *value, *arg, *body;
236
237
name = propname(J);
238
239
if (J->lookahead != ':' && name->type == AST_IDENTIFIER) {
240
if (!strcmp(name->string, "get")) {
241
name = propname(J);
242
jsP_expect(J, '(');
243
jsP_expect(J, ')');
244
body = funbody(J);
245
return EXP3(PROP_GET, name, NULL, body);
246
}
247
if (!strcmp(name->string, "set")) {
248
name = propname(J);
249
jsP_expect(J, '(');
250
arg = identifier(J);
251
jsP_expect(J, ')');
252
body = funbody(J);
253
return EXP3(PROP_SET, name, LIST(arg), body);
254
}
255
}
256
257
jsP_expect(J, ':');
258
value = assignment(J, 0);
259
return EXP2(PROP_VAL, name, value);
260
}
261
262
static js_Ast *objectliteral(js_State *J)
263
{
264
js_Ast *head, *tail;
265
if (J->lookahead == '}')
266
return NULL;
267
head = tail = LIST(propassign(J));
268
while (jsP_accept(J, ',')) {
269
if (J->lookahead == '}')
270
break;
271
tail = tail->b = LIST(propassign(J));
272
}
273
return jsP_list(head);
274
}
275
276
/* Functions */
277
278
static js_Ast *parameters(js_State *J)
279
{
280
js_Ast *head, *tail;
281
if (J->lookahead == ')')
282
return NULL;
283
head = tail = LIST(identifier(J));
284
while (jsP_accept(J, ',')) {
285
tail = tail->b = LIST(identifier(J));
286
}
287
return jsP_list(head);
288
}
289
290
static js_Ast *fundec(js_State *J)
291
{
292
js_Ast *a, *b, *c;
293
a = identifier(J);
294
jsP_expect(J, '(');
295
b = parameters(J);
296
jsP_expect(J, ')');
297
c = funbody(J);
298
return jsP_newnode(J, AST_FUNDEC, a, b, c, 0);
299
}
300
301
static js_Ast *funstm(js_State *J)
302
{
303
js_Ast *a, *b, *c;
304
a = identifier(J);
305
jsP_expect(J, '(');
306
b = parameters(J);
307
jsP_expect(J, ')');
308
c = funbody(J);
309
/* rewrite function statement as "var X = function X() {}" */
310
return STM1(VAR, LIST(EXP2(VAR, a, EXP3(FUN, a, b, c))));
311
}
312
313
static js_Ast *funexp(js_State *J)
314
{
315
js_Ast *a, *b, *c;
316
a = identifieropt(J);
317
jsP_expect(J, '(');
318
b = parameters(J);
319
jsP_expect(J, ')');
320
c = funbody(J);
321
return EXP3(FUN, a, b, c);
322
}
323
324
/* Expressions */
325
326
static js_Ast *primary(js_State *J)
327
{
328
js_Ast *a;
329
330
if (J->lookahead == TK_IDENTIFIER) {
331
checkfutureword(J, J->text);
332
a = jsP_newstrnode(J, EXP_IDENTIFIER, J->text);
333
jsP_next(J);
334
return a;
335
}
336
if (J->lookahead == TK_STRING) {
337
a = jsP_newstrnode(J, EXP_STRING, J->text);
338
jsP_next(J);
339
return a;
340
}
341
if (J->lookahead == TK_REGEXP) {
342
a = jsP_newstrnode(J, EXP_REGEXP, J->text);
343
a->number = J->number;
344
jsP_next(J);
345
return a;
346
}
347
if (J->lookahead == TK_NUMBER) {
348
a = jsP_newnumnode(J, EXP_NUMBER, J->number);
349
jsP_next(J);
350
return a;
351
}
352
353
if (jsP_accept(J, TK_THIS)) return EXP0(THIS);
354
if (jsP_accept(J, TK_NULL)) return EXP0(NULL);
355
if (jsP_accept(J, TK_TRUE)) return EXP0(TRUE);
356
if (jsP_accept(J, TK_FALSE)) return EXP0(FALSE);
357
if (jsP_accept(J, '{')) { a = EXP1(OBJECT, objectliteral(J)); jsP_expect(J, '}'); return a; }
358
if (jsP_accept(J, '[')) { a = EXP1(ARRAY, arrayliteral(J)); jsP_expect(J, ']'); return a; }
359
if (jsP_accept(J, '(')) { a = expression(J, 0); jsP_expect(J, ')'); return a; }
360
361
jsP_error(J, "unexpected token in expression: %s", jsY_tokenstring(J->lookahead));
362
}
363
364
static js_Ast *arguments(js_State *J)
365
{
366
js_Ast *head, *tail;
367
if (J->lookahead == ')')
368
return NULL;
369
head = tail = LIST(assignment(J, 0));
370
while (jsP_accept(J, ',')) {
371
tail = tail->b = LIST(assignment(J, 0));
372
}
373
return jsP_list(head);
374
}
375
376
static js_Ast *newexp(js_State *J)
377
{
378
js_Ast *a, *b;
379
380
if (jsP_accept(J, TK_NEW)) {
381
a = memberexp(J);
382
if (jsP_accept(J, '(')) {
383
b = arguments(J);
384
jsP_expect(J, ')');
385
return EXP2(NEW, a, b);
386
}
387
return EXP1(NEW, a);
388
}
389
390
if (jsP_accept(J, TK_FUNCTION))
391
return funexp(J);
392
393
return primary(J);
394
}
395
396
static js_Ast *memberexp(js_State *J)
397
{
398
js_Ast *a = newexp(J);
399
loop:
400
if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }
401
if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }
402
return a;
403
}
404
405
static js_Ast *callexp(js_State *J)
406
{
407
js_Ast *a = newexp(J);
408
loop:
409
if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }
410
if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }
411
if (jsP_accept(J, '(')) { a = EXP2(CALL, a, arguments(J)); jsP_expect(J, ')'); goto loop; }
412
return a;
413
}
414
415
static js_Ast *postfix(js_State *J)
416
{
417
js_Ast *a = callexp(J);
418
if (!J->newline && jsP_accept(J, TK_INC)) return EXP1(POSTINC, a);
419
if (!J->newline && jsP_accept(J, TK_DEC)) return EXP1(POSTDEC, a);
420
return a;
421
}
422
423
static js_Ast *unary(js_State *J)
424
{
425
if (jsP_accept(J, TK_DELETE)) return EXP1(DELETE, unary(J));
426
if (jsP_accept(J, TK_VOID)) return EXP1(VOID, unary(J));
427
if (jsP_accept(J, TK_TYPEOF)) return EXP1(TYPEOF, unary(J));
428
if (jsP_accept(J, TK_INC)) return EXP1(PREINC, unary(J));
429
if (jsP_accept(J, TK_DEC)) return EXP1(PREDEC, unary(J));
430
if (jsP_accept(J, '+')) return EXP1(POS, unary(J));
431
if (jsP_accept(J, '-')) return EXP1(NEG, unary(J));
432
if (jsP_accept(J, '~')) return EXP1(BITNOT, unary(J));
433
if (jsP_accept(J, '!')) return EXP1(LOGNOT, unary(J));
434
return postfix(J);
435
}
436
437
static js_Ast *multiplicative(js_State *J)
438
{
439
js_Ast *a = unary(J);
440
loop:
441
if (jsP_accept(J, '*')) { a = EXP2(MUL, a, unary(J)); goto loop; }
442
if (jsP_accept(J, '/')) { a = EXP2(DIV, a, unary(J)); goto loop; }
443
if (jsP_accept(J, '%')) { a = EXP2(MOD, a, unary(J)); goto loop; }
444
return a;
445
}
446
447
static js_Ast *additive(js_State *J)
448
{
449
js_Ast *a = multiplicative(J);
450
loop:
451
if (jsP_accept(J, '+')) { a = EXP2(ADD, a, multiplicative(J)); goto loop; }
452
if (jsP_accept(J, '-')) { a = EXP2(SUB, a, multiplicative(J)); goto loop; }
453
return a;
454
}
455
456
static js_Ast *shift(js_State *J)
457
{
458
js_Ast *a = additive(J);
459
loop:
460
if (jsP_accept(J, TK_SHL)) { a = EXP2(SHL, a, additive(J)); goto loop; }
461
if (jsP_accept(J, TK_SHR)) { a = EXP2(SHR, a, additive(J)); goto loop; }
462
if (jsP_accept(J, TK_USHR)) { a = EXP2(USHR, a, additive(J)); goto loop; }
463
return a;
464
}
465
466
static js_Ast *relational(js_State *J, int notin)
467
{
468
js_Ast *a = shift(J);
469
loop:
470
if (jsP_accept(J, '<')) { a = EXP2(LT, a, shift(J)); goto loop; }
471
if (jsP_accept(J, '>')) { a = EXP2(GT, a, shift(J)); goto loop; }
472
if (jsP_accept(J, TK_LE)) { a = EXP2(LE, a, shift(J)); goto loop; }
473
if (jsP_accept(J, TK_GE)) { a = EXP2(GE, a, shift(J)); goto loop; }
474
if (jsP_accept(J, TK_INSTANCEOF)) { a = EXP2(INSTANCEOF, a, shift(J)); goto loop; }
475
if (!notin && jsP_accept(J, TK_IN)) { a = EXP2(IN, a, shift(J)); goto loop; }
476
return a;
477
}
478
479
static js_Ast *equality(js_State *J, int notin)
480
{
481
js_Ast *a = relational(J, notin);
482
loop:
483
if (jsP_accept(J, TK_EQ)) { a = EXP2(EQ, a, relational(J, notin)); goto loop; }
484
if (jsP_accept(J, TK_NE)) { a = EXP2(NE, a, relational(J, notin)); goto loop; }
485
if (jsP_accept(J, TK_STRICTEQ)) { a = EXP2(STRICTEQ, a, relational(J, notin)); goto loop; }
486
if (jsP_accept(J, TK_STRICTNE)) { a = EXP2(STRICTNE, a, relational(J, notin)); goto loop; }
487
return a;
488
}
489
490
static js_Ast *bitand(js_State *J, int notin)
491
{
492
js_Ast *a = equality(J, notin);
493
while (jsP_accept(J, '&'))
494
a = EXP2(BITAND, a, equality(J, notin));
495
return a;
496
}
497
498
static js_Ast *bitxor(js_State *J, int notin)
499
{
500
js_Ast *a = bitand(J, notin);
501
while (jsP_accept(J, '^'))
502
a = EXP2(BITXOR, a, bitand(J, notin));
503
return a;
504
}
505
506
static js_Ast *bitor(js_State *J, int notin)
507
{
508
js_Ast *a = bitxor(J, notin);
509
while (jsP_accept(J, '|'))
510
a = EXP2(BITOR, a, bitxor(J, notin));
511
return a;
512
}
513
514
static js_Ast *logand(js_State *J, int notin)
515
{
516
js_Ast *a = bitor(J, notin);
517
if (jsP_accept(J, TK_AND))
518
a = EXP2(LOGAND, a, logand(J, notin));
519
return a;
520
}
521
522
static js_Ast *logor(js_State *J, int notin)
523
{
524
js_Ast *a = logand(J, notin);
525
if (jsP_accept(J, TK_OR))
526
a = EXP2(LOGOR, a, logor(J, notin));
527
return a;
528
}
529
530
static js_Ast *conditional(js_State *J, int notin)
531
{
532
js_Ast *a, *b, *c;
533
a = logor(J, notin);
534
if (jsP_accept(J, '?')) {
535
b = assignment(J, 0);
536
jsP_expect(J, ':');
537
c = assignment(J, notin);
538
return EXP3(COND, a, b, c);
539
}
540
return a;
541
}
542
543
static js_Ast *assignment(js_State *J, int notin)
544
{
545
js_Ast *a = conditional(J, notin);
546
if (jsP_accept(J, '=')) return EXP2(ASS, a, assignment(J, notin));
547
if (jsP_accept(J, TK_MUL_ASS)) return EXP2(ASS_MUL, a, assignment(J, notin));
548
if (jsP_accept(J, TK_DIV_ASS)) return EXP2(ASS_DIV, a, assignment(J, notin));
549
if (jsP_accept(J, TK_MOD_ASS)) return EXP2(ASS_MOD, a, assignment(J, notin));
550
if (jsP_accept(J, TK_ADD_ASS)) return EXP2(ASS_ADD, a, assignment(J, notin));
551
if (jsP_accept(J, TK_SUB_ASS)) return EXP2(ASS_SUB, a, assignment(J, notin));
552
if (jsP_accept(J, TK_SHL_ASS)) return EXP2(ASS_SHL, a, assignment(J, notin));
553
if (jsP_accept(J, TK_SHR_ASS)) return EXP2(ASS_SHR, a, assignment(J, notin));
554
if (jsP_accept(J, TK_USHR_ASS)) return EXP2(ASS_USHR, a, assignment(J, notin));
555
if (jsP_accept(J, TK_AND_ASS)) return EXP2(ASS_BITAND, a, assignment(J, notin));
556
if (jsP_accept(J, TK_XOR_ASS)) return EXP2(ASS_BITXOR, a, assignment(J, notin));
557
if (jsP_accept(J, TK_OR_ASS)) return EXP2(ASS_BITOR, a, assignment(J, notin));
558
return a;
559
}
560
561
static js_Ast *expression(js_State *J, int notin)
562
{
563
js_Ast *a = assignment(J, notin);
564
while (jsP_accept(J, ','))
565
a = EXP2(COMMA, a, assignment(J, notin));
566
return a;
567
}
568
569
/* Statements */
570
571
static js_Ast *vardec(js_State *J, int notin)
572
{
573
js_Ast *a = identifier(J);
574
if (jsP_accept(J, '='))
575
return EXP2(VAR, a, assignment(J, notin));
576
return EXP1(VAR, a);
577
}
578
579
static js_Ast *vardeclist(js_State *J, int notin)
580
{
581
js_Ast *head, *tail;
582
head = tail = LIST(vardec(J, notin));
583
while (jsP_accept(J, ','))
584
tail = tail->b = LIST(vardec(J, notin));
585
return jsP_list(head);
586
}
587
588
static js_Ast *statementlist(js_State *J)
589
{
590
js_Ast *head, *tail;
591
if (J->lookahead == '}' || J->lookahead == TK_CASE || J->lookahead == TK_DEFAULT)
592
return NULL;
593
head = tail = LIST(statement(J));
594
while (J->lookahead != '}' && J->lookahead != TK_CASE && J->lookahead != TK_DEFAULT)
595
tail = tail->b = LIST(statement(J));
596
return jsP_list(head);
597
}
598
599
static js_Ast *caseclause(js_State *J)
600
{
601
js_Ast *a, *b;
602
603
if (jsP_accept(J, TK_CASE)) {
604
a = expression(J, 0);
605
jsP_expect(J, ':');
606
b = statementlist(J);
607
return STM2(CASE, a, b);
608
}
609
610
if (jsP_accept(J, TK_DEFAULT)) {
611
jsP_expect(J, ':');
612
a = statementlist(J);
613
return STM1(DEFAULT, a);
614
}
615
616
jsP_error(J, "unexpected token in switch: %s (expected 'case' or 'default')", jsY_tokenstring(J->lookahead));
617
}
618
619
static js_Ast *caselist(js_State *J)
620
{
621
js_Ast *head, *tail;
622
if (J->lookahead == '}')
623
return NULL;
624
head = tail = LIST(caseclause(J));
625
while (J->lookahead != '}')
626
tail = tail->b = LIST(caseclause(J));
627
return jsP_list(head);
628
}
629
630
static js_Ast *block(js_State *J)
631
{
632
js_Ast *a;
633
jsP_expect(J, '{');
634
a = statementlist(J);
635
jsP_expect(J, '}');
636
return STM1(BLOCK, a);
637
}
638
639
static js_Ast *forexpression(js_State *J, int end)
640
{
641
js_Ast *a = NULL;
642
if (J->lookahead != end)
643
a = expression(J, 0);
644
jsP_expect(J, end);
645
return a;
646
}
647
648
static js_Ast *forstatement(js_State *J)
649
{
650
js_Ast *a, *b, *c, *d;
651
jsP_expect(J, '(');
652
if (jsP_accept(J, TK_VAR)) {
653
a = vardeclist(J, 1);
654
if (jsP_accept(J, ';')) {
655
b = forexpression(J, ';');
656
c = forexpression(J, ')');
657
d = statement(J);
658
return STM4(FOR_VAR, a, b, c, d);
659
}
660
if (jsP_accept(J, TK_IN)) {
661
b = expression(J, 0);
662
jsP_expect(J, ')');
663
c = statement(J);
664
return STM3(FOR_IN_VAR, a, b, c);
665
}
666
jsP_error(J, "unexpected token in for-var-statement: %s", jsY_tokenstring(J->lookahead));
667
}
668
669
if (J->lookahead != ';')
670
a = expression(J, 1);
671
else
672
a = NULL;
673
if (jsP_accept(J, ';')) {
674
b = forexpression(J, ';');
675
c = forexpression(J, ')');
676
d = statement(J);
677
return STM4(FOR, a, b, c, d);
678
}
679
if (jsP_accept(J, TK_IN)) {
680
b = expression(J, 0);
681
jsP_expect(J, ')');
682
c = statement(J);
683
return STM3(FOR_IN, a, b, c);
684
}
685
jsP_error(J, "unexpected token in for-statement: %s", jsY_tokenstring(J->lookahead));
686
}
687
688
static js_Ast *statement(js_State *J)
689
{
690
js_Ast *a, *b, *c, *d;
691
692
if (J->lookahead == '{') {
693
return block(J);
694
}
695
696
if (jsP_accept(J, TK_VAR)) {
697
a = vardeclist(J, 0);
698
semicolon(J);
699
return STM1(VAR, a);
700
}
701
702
/* empty statement */
703
if (jsP_accept(J, ';')) {
704
return STM0(EMPTY);
705
}
706
707
if (jsP_accept(J, TK_IF)) {
708
jsP_expect(J, '(');
709
a = expression(J, 0);
710
jsP_expect(J, ')');
711
b = statement(J);
712
if (jsP_accept(J, TK_ELSE))
713
c = statement(J);
714
else
715
c = NULL;
716
return STM3(IF, a, b, c);
717
}
718
719
if (jsP_accept(J, TK_DO)) {
720
a = statement(J);
721
jsP_expect(J, TK_WHILE);
722
jsP_expect(J, '(');
723
b = expression(J, 0);
724
jsP_expect(J, ')');
725
semicolon(J);
726
return STM2(DO, a, b);
727
}
728
729
if (jsP_accept(J, TK_WHILE)) {
730
jsP_expect(J, '(');
731
a = expression(J, 0);
732
jsP_expect(J, ')');
733
b = statement(J);
734
return STM2(WHILE, a, b);
735
}
736
737
if (jsP_accept(J, TK_FOR)) {
738
return forstatement(J);
739
}
740
741
if (jsP_accept(J, TK_CONTINUE)) {
742
a = identifieropt(J);
743
semicolon(J);
744
return STM1(CONTINUE, a);
745
}
746
747
if (jsP_accept(J, TK_BREAK)) {
748
a = identifieropt(J);
749
semicolon(J);
750
return STM1(BREAK, a);
751
}
752
753
if (jsP_accept(J, TK_RETURN)) {
754
if (J->lookahead != ';' && J->lookahead != '}' && J->lookahead != 0)
755
a = expression(J, 0);
756
else
757
a = NULL;
758
semicolon(J);
759
return STM1(RETURN, a);
760
}
761
762
if (jsP_accept(J, TK_WITH)) {
763
if (J->strict)
764
jsP_error(J, "'with' statements are not allowed in strict mode");
765
jsP_expect(J, '(');
766
a = expression(J, 0);
767
jsP_expect(J, ')');
768
b = statement(J);
769
return STM2(WITH, a, b);
770
}
771
772
if (jsP_accept(J, TK_SWITCH)) {
773
jsP_expect(J, '(');
774
a = expression(J, 0);
775
jsP_expect(J, ')');
776
jsP_expect(J, '{');
777
b = caselist(J);
778
jsP_expect(J, '}');
779
return STM2(SWITCH, a, b);
780
}
781
782
if (jsP_accept(J, TK_THROW)) {
783
a = expression(J, 0);
784
semicolon(J);
785
return STM1(THROW, a);
786
}
787
788
if (jsP_accept(J, TK_TRY)) {
789
a = block(J);
790
b = c = d = NULL;
791
if (jsP_accept(J, TK_CATCH)) {
792
jsP_expect(J, '(');
793
b = identifier(J);
794
jsP_expect(J, ')');
795
c = block(J);
796
}
797
if (jsP_accept(J, TK_FINALLY)) {
798
d = block(J);
799
}
800
if (!b && !d)
801
jsP_error(J, "unexpected token in try: %s (expected 'catch' or 'finally')", jsY_tokenstring(J->lookahead));
802
return STM4(TRY, a, b, c, d);
803
}
804
805
if (jsP_accept(J, TK_DEBUGGER)) {
806
semicolon(J);
807
return STM0(DEBUGGER);
808
}
809
810
if (jsP_accept(J, TK_FUNCTION)) {
811
jsP_warning(J, "function statements are not standard");
812
return funstm(J);
813
}
814
815
/* labelled statement or expression statement */
816
if (J->lookahead == TK_IDENTIFIER) {
817
a = expression(J, 0);
818
if (a->type == EXP_IDENTIFIER && jsP_accept(J, ':')) {
819
a->type = AST_IDENTIFIER;
820
b = statement(J);
821
return STM2(LABEL, a, b);
822
}
823
semicolon(J);
824
return a;
825
}
826
827
/* expression statement */
828
a = expression(J, 0);
829
semicolon(J);
830
return a;
831
}
832
833
/* Program */
834
835
static js_Ast *scriptelement(js_State *J)
836
{
837
if (jsP_accept(J, TK_FUNCTION))
838
return fundec(J);
839
return statement(J);
840
}
841
842
static js_Ast *script(js_State *J, int terminator)
843
{
844
js_Ast *head, *tail;
845
if (J->lookahead == terminator)
846
return NULL;
847
head = tail = LIST(scriptelement(J));
848
while (J->lookahead != terminator)
849
tail = tail->b = LIST(scriptelement(J));
850
return jsP_list(head);
851
}
852
853
static js_Ast *funbody(js_State *J)
854
{
855
js_Ast *a;
856
jsP_expect(J, '{');
857
a = script(J, '}');
858
jsP_expect(J, '}');
859
return a;
860
}
861
862
/* Constant folding */
863
864
static int toint32(double d)
865
{
866
double two32 = 4294967296.0;
867
double two31 = 2147483648.0;
868
869
if (!isfinite(d) || d == 0)
870
return 0;
871
872
d = fmod(d, two32);
873
d = d >= 0 ? floor(d) : ceil(d) + two32;
874
if (d >= two31)
875
return d - two32;
876
else
877
return d;
878
}
879
880
static unsigned int touint32(double d)
881
{
882
return toint32(d);
883
}
884
885
static int jsP_setnumnode(js_Ast *node, double x)
886
{
887
node->type = EXP_NUMBER;
888
node->number = x;
889
node->a = node->b = node->c = node->d = NULL;
890
return 1;
891
}
892
893
static int jsP_foldconst(js_Ast *node)
894
{
895
double x, y;
896
int a, b;
897
898
if (node->type == EXP_NUMBER)
899
return 1;
900
901
a = node->a ? jsP_foldconst(node->a) : 0;
902
b = node->b ? jsP_foldconst(node->b) : 0;
903
if (node->c) jsP_foldconst(node->c);
904
if (node->d) jsP_foldconst(node->d);
905
906
if (a) {
907
x = node->a->number;
908
switch (node->type) {
909
case EXP_NEG: return jsP_setnumnode(node, -x);
910
case EXP_POS: return jsP_setnumnode(node, x);
911
case EXP_BITNOT: return jsP_setnumnode(node, ~toint32(x));
912
}
913
914
if (b) {
915
y = node->b->number;
916
switch (node->type) {
917
case EXP_MUL: return jsP_setnumnode(node, x * y);
918
case EXP_DIV: return jsP_setnumnode(node, x / y);
919
case EXP_MOD: return jsP_setnumnode(node, fmod(x, y));
920
case EXP_ADD: return jsP_setnumnode(node, x + y);
921
case EXP_SUB: return jsP_setnumnode(node, x - y);
922
case EXP_SHL: return jsP_setnumnode(node, toint32(x) << (touint32(y) & 0x1F));
923
case EXP_SHR: return jsP_setnumnode(node, toint32(x) >> (touint32(y) & 0x1F));
924
case EXP_USHR: return jsP_setnumnode(node, touint32(x) >> (touint32(y) & 0x1F));
925
case EXP_BITAND: return jsP_setnumnode(node, toint32(x) & toint32(y));
926
case EXP_BITXOR: return jsP_setnumnode(node, toint32(x) ^ toint32(y));
927
case EXP_BITOR: return jsP_setnumnode(node, toint32(x) | toint32(y));
928
}
929
}
930
}
931
932
return 0;
933
}
934
935
/* Main entry point */
936
937
js_Ast *jsP_parse(js_State *J, const char *filename, const char *source)
938
{
939
js_Ast *p;
940
941
jsY_initlex(J, filename, source);
942
jsP_next(J);
943
p = script(J, 0);
944
if (p)
945
jsP_foldconst(p);
946
947
return p;
948
}
949
950
js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body)
951
{
952
js_Ast *p = NULL;
953
if (params) {
954
jsY_initlex(J, filename, params);
955
jsP_next(J);
956
p = parameters(J);
957
}
958
return EXP3(FUN, NULL, p, jsP_parse(J, filename, body));
959
}
960
961