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