comparison mupdf-source/thirdparty/mujs/jsparse.c @ 2:b50eed0cc0ef upstream

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