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