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
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 #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
jsP_error(js_State * J,const char * fmt,...)31 static 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
jsP_warning(js_State * J,const char * fmt,...)48 static 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
jsP_newnode(js_State * J,enum js_AstType type,int line,js_Ast * a,js_Ast * b,js_Ast * c,js_Ast * d)62 static 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
jsP_list(js_Ast * head)89 static 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
jsP_newstrnode(js_State * J,enum js_AstType type,const char * s)101 static 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
jsP_newnumnode(js_State * J,enum js_AstType type,double n)108 static 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
jsP_freejumps(js_State * J,js_JumpList * node)115 static 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
jsP_freeparse(js_State * J)124 void 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
jsP_next(js_State * J)138 static 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
semicolon(js_State * J)147 static 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
identifier(js_State * J)160 static 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
identifieropt(js_State * J)171 static js_Ast *identifieropt(js_State *J)
172 {
173 if (J->lookahead == TK_IDENTIFIER)
174 return identifier(J);
175 return NULL;
176 }
177
identifiername(js_State * J)178 static 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
arrayelement(js_State * J)188 static 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
arrayliteral(js_State * J)196 static 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
propname(js_State * J)209 static 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
propassign(js_State * J)224 static 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
objectliteral(js_State * J)254 static 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
parameters(js_State * J)270 static 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
fundec(js_State * J,int line)282 static 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
funstm(js_State * J,int line)293 static 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
funexp(js_State * J,int line)305 static 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
primary(js_State * J)318 static 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
arguments(js_State * J)368 static 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
newexp(js_State * J)380 static 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
memberexp(js_State * J)401 static js_Ast *memberexp(js_State *J)
402 {
403 js_Ast *a = newexp(J);
404 int line;
405 SAVEREC();
406 loop:
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
callexp(js_State * J)415 static js_Ast *callexp(js_State *J)
416 {
417 js_Ast *a = newexp(J);
418 int line;
419 SAVEREC();
420 loop:
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
postfix(js_State * J)430 static 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
unary(js_State * J)439 static 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
multiplicative(js_State * J)458 static js_Ast *multiplicative(js_State *J)
459 {
460 js_Ast *a = unary(J);
461 int line;
462 SAVEREC();
463 loop:
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
additive(js_State * J)473 static js_Ast *additive(js_State *J)
474 {
475 js_Ast *a = multiplicative(J);
476 int line;
477 SAVEREC();
478 loop:
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
shift(js_State * J)487 static js_Ast *shift(js_State *J)
488 {
489 js_Ast *a = additive(J);
490 int line;
491 SAVEREC();
492 loop:
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
relational(js_State * J,int notin)502 static js_Ast *relational(js_State *J, int notin)
503 {
504 js_Ast *a = shift(J);
505 int line;
506 SAVEREC();
507 loop:
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
equality(js_State * J,int notin)520 static js_Ast *equality(js_State *J, int notin)
521 {
522 js_Ast *a = relational(J, notin);
523 int line;
524 SAVEREC();
525 loop:
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
bitand(js_State * J,int notin)536 static 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
bitxor(js_State * J,int notin)550 static 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
bitor(js_State * J,int notin)564 static 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
logand(js_State * J,int notin)578 static 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
logor(js_State * J,int notin)590 static 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
conditional(js_State * J,int notin)602 static 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
assignment(js_State * J,int notin)618 static 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
expression(js_State * J,int notin)639 static 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
vardec(js_State * J,int notin)655 static 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
vardeclist(js_State * J,int notin)664 static 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
statementlist(js_State * J)673 static 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
caseclause(js_State * J)684 static 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
caselist(js_State * J)705 static 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
block(js_State * J)716 static 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
forexpression(js_State * J,int end)726 static 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
forstatement(js_State * J,int line)735 static 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
statement(js_State * J)775 static 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
scriptelement(js_State * J)929 static 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
script(js_State * J,int terminator)937 static 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
funbody(js_State * J)948 static 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
toint32(double d)959 static 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
touint32(double d)975 static unsigned int touint32(double d)
976 {
977 return (unsigned int)toint32(d);
978 }
979
jsP_setnumnode(js_Ast * node,double x)980 static 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
jsP_foldconst(js_Ast * node)988 static 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
jsP_parse(js_State * J,const char * filename,const char * source)1042 js_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
jsP_parsefunction(js_State * J,const char * filename,const char * params,const char * body)1056 js_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