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