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