MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1#include "silver/ast.h"
2#include "silver/lexer.h"
3#include "silver/directives.h"
4
5#include "escape.h"
6#include "debug.h"
7#include "errors.h"
8#include "internal.h"
9#include "tokens.h"
10
11#include <runtime.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16sv_ast_t *sv_ast_new(sv_node_type_t type) {
17 sv_ast_t *n = parse_arena_bump(sizeof(sv_ast_t));
18 if (!n) return NULL;
19 memset(n, 0, sizeof(sv_ast_t));
20 n->type = type;
21 return n;
22}
23
24void sv_ast_list_push(sv_ast_list_t *list, sv_ast_t *node) {
25 if (list->count >= list->cap) {
26 int new_cap = list->cap ? list->cap * 2 : 4;
27 sv_ast_t **new_items = parse_arena_bump((size_t)new_cap * sizeof(sv_ast_t *));
28 if (!new_items) return;
29 if (list->items)
30 memcpy(new_items, list->items, (size_t)list->count * sizeof(sv_ast_t *));
31 list->items = new_items;
32 list->cap = new_cap;
33 }
34 list->items[list->count++] = node;
35}
36
37bool sv_ast_can_be_expression_statement(const sv_ast_t *node) {
38 if (!node) return false;
39 if ((node->type == N_FUNC || node->type == N_CLASS) && (node->flags & FN_PAREN)) return true;
40
41 static const uint8_t expr_stmt_nodes[N__COUNT] = {
42 [N_NUMBER] = 1, [N_STRING] = 1, [N_BIGINT] = 1, [N_BOOL] = 1,
43 [N_NULL] = 1, [N_UNDEF] = 1, [N_THIS] = 1, [N_GLOBAL_THIS] = 1,
44 [N_TEMPLATE] = 1, [N_REGEXP] = 1, [N_IDENT] = 1, [N_BINARY] = 1,
45 [N_UNARY] = 1, [N_UPDATE] = 1, [N_ASSIGN] = 1, [N_TERNARY] = 1,
46 [N_CALL] = 1, [N_NEW] = 1, [N_MEMBER] = 1, [N_OPTIONAL] = 1,
47 [N_ARRAY] = 1, [N_OBJECT] = 1, [N_PROPERTY] = 1, [N_SPREAD] = 1,
48 [N_SEQUENCE] = 1, [N_ARROW] = 1, [N_YIELD] = 1, [N_AWAIT] = 1,
49 [N_TYPEOF] = 1, [N_DELETE] = 1, [N_VOID] = 1, [N_TAGGED_TEMPLATE] = 1,
50 [N_IMPORT] = 1,
51 };
52
53 if (node->type == N_FUNC)
54 return !(node->str && !(node->flags & FN_ARROW));
55 if ((unsigned)node->type >= N__COUNT) return false;
56 return expr_stmt_nodes[node->type] != 0;
57}
58
59typedef struct {
60 ant_t *js;
61 sv_lexer_t lx;
62 bool no_in;
63} sv_parser_t;
64
65#define P sv_parser_t *p
66#define JS p->js
67#define TOK p->lx.st.tok
68#define TOFF p->lx.st.toff
69#define TLEN p->lx.st.tlen
70#define TVAL p->lx.st.tval
71#define POS p->lx.st.pos
72#define CONSUMED p->lx.st.consumed
73#define HAD_NEWLINE p->lx.st.had_newline
74#define CODE p->lx.code
75#define CLEN p->lx.clen
76#define CONSUME() ((void)(CONSUMED = 1))
77#define NEXT() sv_lexer_next(&p->lx)
78#define LA() sv_lexer_lookahead(&p->lx)
79
80static bool lookahead_crosses_line_terminator(P) {
81 sv_lexer_state_t saved;
82 sv_lexer_save_state(&p->lx, &saved);
83 CONSUMED = 1;
84 (void)NEXT();
85 bool had_newline = HAD_NEWLINE;
86 sv_lexer_restore_state(&p->lx, &saved);
87 return had_newline;
88}
89
90static sv_ast_t *parse_stmt(P);
91static sv_ast_t *parse_expr(P);
92static sv_ast_t *parse_paren_expr(P);
93static sv_ast_t *parse_assign(P);
94static sv_ast_t *parse_ternary(P);
95static sv_ast_t *parse_binary(P, int min_prec);
96static sv_ast_t *parse_unary(P);
97static sv_ast_t *parse_postfix(P);
98static sv_ast_t *parse_call(P);
99static sv_ast_t *parse_primary(P);
100static sv_ast_t *parse_block(P, bool directive_ctx);
101static sv_ast_t *parse_func(P);
102static sv_ast_t *parse_class(P);
103static sv_ast_t *parse_object(P);
104static sv_ast_t *parse_array(P);
105static sv_ast_t *parse_import_stmt(P);
106static sv_ast_t *parse_export_stmt(P);
107static sv_ast_t *parse_arrow_body(P);
108static sv_ast_t *parse_binding_pattern(P);
109
110#define SV_SYNC_ERR() ((void)sv_lexer_set_error_site(&p->lx))
111#define SV_MKERR(...) (SV_SYNC_ERR(), js_mkerr(__VA_ARGS__))
112#define SV_MKERR_TYPED(...) (SV_SYNC_ERR(), js_mkerr_typed(__VA_ARGS__))
113
114static inline const char *tok_str(P) {
115 return &CODE[TOFF];
116}
117
118static inline bool eat(P, uint8_t tok) {
119 NEXT();
120 if (TOK == tok) { CONSUME(); return true; }
121 return false;
122}
123
124static inline void expect(P, uint8_t tok) {
125 NEXT();
126 if (TOK == tok) CONSUME();
127}
128
129static inline sv_ast_t *mk_plain(sv_node_type_t type) {
130 return sv_ast_new(type);
131}
132
133#define mk(type) ({ \
134 sv_ast_t *_n = mk_plain(type); \
135 _n->src_off = (uint32_t)TOFF; _n; \
136})
137
138static inline sv_ast_t *mk_num(double val) {
139 sv_ast_t *n = mk_plain(N_NUMBER);
140 n->num = val;
141 return n;
142}
143
144static inline sv_ast_t *mk_ident(const char *s, uint32_t len) {
145 sv_ast_t *n = mk_plain(N_IDENT);
146 n->str = s;
147 n->len = len;
148 return n;
149}
150
151static inline void sv_ast_set_string(sv_ast_t *n, sv_lex_string_t s) {
152 if (!n || !s.ok) return;
153 n->str = s.str;
154 n->len = s.len;
155}
156
157typedef struct {
158 const char *str;
159 uint32_t len;
160 bool ok;
161 bool valid_cooked;
162} sv_tpl_cooked_t;
163
164static inline const char *decode_ident_into_arena(const char *src, uint32_t len, uint32_t *out_len) {
165 if (!src || len == 0 || !memchr(src, '\\', len)) {
166 if (out_len) *out_len = len;
167 return src;
168 }
169
170 char *dst = parse_arena_bump((size_t)len + 1);
171 if (!dst) {
172 if (out_len) *out_len = len;
173 return src;
174 }
175
176 size_t di = 0; size_t i = 0;
177 const uint8_t *in = (const uint8_t *)src;
178 uint8_t *out = (uint8_t *)dst;
179
180 while (i < len) {
181 if (in[i] == '\\' && i + 1 < len && in[i + 1] == 'u') {
182 size_t adv = decode_escape(in, i, len, out, &di, 0);
183 if (adv > 0) { i += 2 + adv; continue; }
184 }
185 out[di++] = in[i++];
186 }
187
188 out[di] = '\0';
189 if (out_len) *out_len = (uint32_t)di;
190 return dst;
191}
192
193static inline bool is_contextual_ident_tok(uint8_t tok) {
194 return
195 tok == TOK_AS ||
196 tok == TOK_FROM ||
197 tok == TOK_OF ||
198 tok == TOK_ASYNC ||
199 tok == TOK_USING;
200}
201
202static inline const char *tok_ident_str(P, uint32_t *out_len) {
203 return decode_ident_into_arena(tok_str(p), (uint32_t)TLEN, out_len);
204}
205
206static inline bool is_ident_like_tok(uint8_t tok) {
207 return tok == TOK_IDENTIFIER || tok == TOK_DEFAULT || is_contextual_ident_tok(tok);
208}
209
210static inline bool is_private_ident_like_tok(uint8_t tok) {
211 return tok >= TOK_IDENTIFIER && tok < TOK_IDENT_LIKE_END;
212}
213
214static inline bool sv_strict_forbidden_binding_ident(const char *s, uint32_t len) {
215 return is_eval_or_arguments_name(s, len) || is_strict_reserved_name(s, len);
216}
217
218static inline bool sv_is_strict_restricted_assign_target(P, sv_ast_t *n) {
219 return p->lx.strict && n && n->type == N_IDENT && is_eval_or_arguments_name(n->str, n->len);
220}
221
222static inline sv_ast_t *mk_ident_from_tok(P) {
223 uint32_t len = 0;
224 const char *name = tok_ident_str(p, &len);
225 sv_ast_t *n = mk_ident(name, len);
226 n->src_off = (uint32_t)TOFF;
227 n->src_end = (uint32_t)(TOFF + TLEN);
228 return n;
229}
230
231static inline sv_ast_t *mk_private_ident_from_tok(P) {
232 sv_ast_t *n = mk(N_IDENT);
233 n->str = &CODE[TOFF - 1];
234 n->len = (uint32_t)(TLEN + 1);
235 n->src_off = (uint32_t)(TOFF > 0 ? TOFF - 1 : TOFF);
236 n->src_end = (uint32_t)(TOFF + TLEN);
237 return n;
238}
239
240static inline void sv_strict_check_binding_ident(P, const char *s, uint32_t len) {
241 if (!p->lx.strict || !s || len == 0) return;
242 if (sv_strict_forbidden_binding_ident(s, len)) SV_MKERR_TYPED(
243 JS, JS_ERR_SYNTAX, "Invalid binding identifier '%.*s' in strict mode",
244 (int)len, s
245 );
246}
247
248static inline void sv_parse_unexpected_token(P) {
249 size_t tok_len = 0;
250
251 if (TOFF < CLEN && TLEN > 0) {
252 ant_offset_t rem = CLEN - TOFF;
253 tok_len = (size_t)TLEN;
254 if ((ant_offset_t)tok_len > rem) tok_len = (size_t)rem;
255 }
256
257 if (tok_len == 0) {
258 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Unexpected token 'EOF'");
259 return;
260 }
261
262 SV_MKERR_TYPED(
263 JS, JS_ERR_SYNTAX,
264 "Unexpected token '%.*s'",
265 (int)tok_len, &CODE[TOFF]
266 );
267}
268
269static inline sv_ast_t *parse_dot_property_name(P) {
270 if (!is_private_ident_like_tok(TOK)) {
271 sv_parse_unexpected_token(p);
272 return NULL;
273 }
274
275 sv_ast_t *name = mk_ident_from_tok(p);
276 CONSUME();
277 return name;
278}
279
280static sv_ast_t *parse_arrow_body(P) {
281 if (NEXT() == TOK_LBRACE) return parse_block(p, true);
282 return parse_assign(p);
283}
284
285static inline uint32_t node_src_end(P, sv_ast_t *node) {
286 if (node && node->src_end > node->src_off) return node->src_end;
287 return (uint32_t)(TOFF + TLEN);
288}
289
290static void sv_parse_stmt_list(P, sv_ast_list_t *out, bool stop_at_rbrace, bool directive_ctx) {
291 bool strict_mode = p->lx.strict;
292 bool saved_lexer_strict = p->lx.strict;
293 bool in_directive_prologue = directive_ctx;
294 p->lx.strict = strict_mode;
295
296 for (;;) {
297 NEXT();
298 if (TOK == TOK_EOF) break;
299 if (stop_at_rbrace && TOK == TOK_RBRACE) break;
300
301 if (TOK == TOK_ERR) {
302 sv_parse_unexpected_token(p);
303 break;
304 }
305
306 sv_ast_t *stmt = parse_stmt(p);
307 if (stmt) sv_ast_list_push(out, stmt);
308 if (JS->thrown_exists) break;
309 if (!in_directive_prologue) continue;
310 if (!stmt || stmt->type == N_EMPTY) continue;
311
312 if (!sv_ast_can_be_expression_statement(stmt)) {
313 in_directive_prologue = false;
314 continue;
315 }
316
317 if (sv_ast_is_use_strict(JS, stmt)) {
318 strict_mode = true;
319 p->lx.strict = true;
320 continue;
321 }
322 in_directive_prologue = false;
323 }
324 p->lx.strict = saved_lexer_strict;
325}
326
327static sv_ast_t *parse_binding_pattern(P) {
328 NEXT();
329 if (TOK == TOK_LBRACKET) return parse_array(p);
330 if (TOK == TOK_LBRACE) return parse_object(p);
331 if (is_ident_like_tok(TOK)) {
332 sv_ast_t *id = mk_ident_from_tok(p);
333 sv_strict_check_binding_ident(p, id->str, id->len);
334 CONSUME();
335 return id;
336 }
337 CONSUME();
338 return mk(N_EMPTY);
339}
340
341static void push_arrow_params_from_expr(sv_ast_t *fn, sv_ast_t *expr) {
342 if (!fn || !expr) return;
343 if (expr->type == N_SEQUENCE) {
344 push_arrow_params_from_expr(fn, expr->left);
345 push_arrow_params_from_expr(fn, expr->right);
346 return;
347 }
348 if (expr->type == N_ASSIGN && expr->op == TOK_ASSIGN) {
349 sv_ast_t *def = mk_plain(N_ASSIGN_PAT);
350 def->left = expr->left;
351 def->right = expr->right;
352 def->src_off = expr->src_off;
353 sv_ast_list_push(&fn->args, def);
354 return;
355 }
356 if (expr->type == N_SPREAD) {
357 sv_ast_t *rest = mk_plain(N_REST);
358 rest->right = expr->right;
359 rest->src_off = expr->src_off;
360 sv_ast_list_push(&fn->args, rest);
361 return;
362 }
363 sv_ast_list_push(&fn->args, expr);
364}
365
366static sv_tpl_cooked_t decode_template_segment(P, const uint8_t *in, size_t start, size_t end) {
367 sv_tpl_cooked_t outv = { .str = NULL, .len = 0, .ok = true, .valid_cooked = true };
368 size_t raw_len = (end > start) ? (end - start) : 0;
369 if (raw_len == 0) {
370 outv.str = "";
371 return outv;
372 }
373
374 uint8_t *out = parse_arena_bump(raw_len);
375 if (!out) {
376 (void)SV_MKERR(JS, "oom");
377 outv.ok = false;
378 return outv;
379 }
380
381 size_t out_len = 0;
382 for (size_t i = start; i < end; i++) {
383 if (in[i] == '\r') {
384 out[out_len++] = '\n';
385 if (i + 1 < end && in[i + 1] == '\n') i++;
386 continue;
387 }
388 if (in[i] != '\\' || i + 1 >= end) {
389 out[out_len++] = in[i];
390 continue;
391 }
392 uint8_t c = in[i + 1];
393 if (c >= '1' && c <= '9') { outv.valid_cooked = false; return outv; }
394 if (c == '0' && i + 2 < end && in[i + 2] >= '0' && in[i + 2] <= '9') {
395 outv.valid_cooked = false; return outv;
396 }
397 if (c == 'x' && !(i + 3 < end && is_xdigit(in[i + 2]) && is_xdigit(in[i + 3]))) {
398 outv.valid_cooked = false; return outv;
399 }
400 if (c == 'u') {
401 if (i + 2 < end && in[i + 2] == '{') {
402 uint32_t cp = 0; size_t j = i + 3;
403 while (j < end && is_xdigit(in[j])) { cp = (cp << 4) | unhex(in[j]); j++; }
404 if (!(j < end && in[j] == '}' && j > i + 3 && cp <= 0x10FFFF)) {
405 outv.valid_cooked = false; return outv;
406 }
407 } else if (
408 !(i + 5 < end && is_xdigit(in[i + 2])
409 && is_xdigit(in[i + 3])
410 && is_xdigit(in[i + 4])
411 && is_xdigit(in[i + 5]))) { outv.valid_cooked = false; return outv; }
412 }
413 i += 1 + decode_escape(in, i, end, out, &out_len, '`');
414 }
415
416 outv.str = (const char *)out;
417 outv.len = (uint32_t)out_len;
418 return outv;
419}
420
421static sv_ast_t *try_parse_async_arrow(P) {
422 uint8_t la = LA();
423 uint32_t async_off = (uint32_t)TOFF;
424
425 if (la == TOK_LPAREN) {
426 sv_lexer_state_t saved;
427 sv_lexer_save_state(&p->lx, &saved);
428 NEXT(); CONSUME();
429 if (NEXT() == TOK_RPAREN) {
430 CONSUME();
431 if (LA() == TOK_ARROW) {
432 NEXT(); CONSUME();
433 sv_ast_t *fn = mk(N_FUNC);
434 fn->flags = FN_ARROW | FN_ASYNC;
435 fn->body = parse_arrow_body(p);
436 fn->src_off = async_off;
437 fn->src_end = node_src_end(p, fn->body);
438 return fn;
439 }
440 }
441 sv_lexer_restore_state(&p->lx, &saved);
442 NEXT(); CONSUME();
443 sv_ast_t *expr = parse_paren_expr(p);
444 expect(p, TOK_RPAREN);
445 if (LA() == TOK_ARROW) {
446 NEXT(); CONSUME();
447 sv_ast_t *fn = mk(N_FUNC);
448 fn->flags = FN_ARROW | FN_ASYNC;
449 push_arrow_params_from_expr(fn, expr);
450 fn->body = parse_arrow_body(p);
451 fn->src_off = async_off;
452 fn->src_end = node_src_end(p, fn->body);
453 return fn;
454 }
455 sv_lexer_restore_state(&p->lx, &saved);
456 return NULL;
457 }
458
459 if (la == TOK_IDENTIFIER) {
460 sv_lexer_state_t saved;
461 sv_lexer_save_state(&p->lx, &saved);
462 NEXT(); CONSUME();
463 sv_ast_t *id = mk_ident_from_tok(p);
464 if (LA() == TOK_ARROW) {
465 NEXT(); CONSUME();
466 sv_ast_t *fn = mk(N_FUNC);
467 fn->flags = FN_ARROW | FN_ASYNC;
468 sv_ast_list_push(&fn->args, id);
469 fn->body = parse_arrow_body(p);
470 fn->src_off = async_off;
471 fn->src_end = node_src_end(p, fn->body);
472 return fn;
473 }
474 sv_lexer_restore_state(&p->lx, &saved);
475 return NULL;
476 }
477
478 return NULL;
479}
480
481static sv_ast_t *parse_primary(P) {
482 NEXT();
483
484 static const void *dispatch[TOK_MAX] = {
485 [TOK_NUMBER] = &&l_number,
486 [TOK_STRING] = &&l_string,
487 [TOK_BIGINT] = &&l_bigint,
488 [TOK_TRUE] = &&l_true,
489 [TOK_FALSE] = &&l_false,
490 [TOK_NULL] = &&l_null,
491 [TOK_UNDEF] = &&l_undef,
492 [TOK_THIS] = &&l_this,
493 [TOK_IDENTIFIER] = &&l_ident,
494 [TOK_AS] = &&l_ident,
495 [TOK_FROM] = &&l_ident,
496 [TOK_OF] = &&l_ident,
497 [TOK_USING] = &&l_ident,
498 [TOK_LPAREN] = &&l_paren,
499 [TOK_LBRACKET] = &&l_array,
500 [TOK_LBRACE] = &&l_object,
501 [TOK_FUNC] = &&l_func,
502 [TOK_CLASS] = &&l_class,
503 [TOK_ASYNC] = &&l_async,
504 [TOK_TEMPLATE] = &&l_template,
505 [TOK_NEW] = &&l_new,
506 [TOK_TYPEOF] = &&l_typeof,
507 [TOK_VOID] = &&l_void,
508 [TOK_DELETE] = &&l_delete,
509 [TOK_YIELD] = &&l_yield,
510 [TOK_AWAIT] = &&l_await,
511 [TOK_SUPER] = &&l_super,
512 [TOK_REST] = &&l_spread,
513 [TOK_IMPORT] = &&l_import_expr,
514 [TOK_DIV] = &&l_regex,
515 [TOK_DIV_ASSIGN] = &&l_regex,
516 [TOK_GLOBAL_THIS] = &&l_globalthis,
517 [TOK_WINDOW] = &&l_globalthis,
518 [TOK_HASH] = &&l_private_name,
519 };
520
521 if (TOK < TOK_MAX && dispatch[TOK])
522 goto *dispatch[TOK];
523
524 sv_parse_unexpected_token(p);
525 return mk(N_EMPTY);
526
527 l_number: {
528 CONSUME();
529 return mk_num(tod(TVAL));
530 }
531
532 l_string: {
533 sv_ast_t *n = mk(N_STRING);
534 sv_ast_set_string(n, sv_lexer_str_literal(&p->lx));
535 CONSUME();
536 return n;
537 }
538
539 l_bigint: {
540 CONSUME();
541 sv_ast_t *n = mk(N_BIGINT);
542 n->str = tok_str(p);
543 n->len = (uint32_t)TLEN;
544 return n;
545 }
546
547 l_true: { CONSUME(); sv_ast_t *n = mk(N_BOOL); n->num = 1; return n; }
548 l_false: { CONSUME(); sv_ast_t *n = mk(N_BOOL); n->num = 0; return n; }
549 l_null: { CONSUME(); return mk(N_NULL); }
550 l_undef: { CONSUME(); return mk(N_UNDEF); }
551 l_this: { CONSUME(); return mk(N_THIS); }
552 l_globalthis: { CONSUME(); return mk(N_GLOBAL_THIS); }
553
554 l_ident: {
555 CONSUME();
556 return mk_ident_from_tok(p);
557 }
558
559 l_paren: {
560 uint32_t paren_off = (uint32_t)TOFF;
561 CONSUME();
562 if (NEXT() == TOK_RPAREN) {
563 CONSUME();
564 sv_ast_t *n = mk(N_UNDEF);
565 n->flags |= FN_PAREN;
566 n->src_off = paren_off;
567 return n;
568 }
569 sv_ast_t *expr = parse_paren_expr(p);
570 expect(p, TOK_RPAREN);
571 expr->flags |= FN_PAREN;
572 if (expr->type != N_FUNC && expr->type != N_CLASS) expr->src_off = paren_off;
573 return expr;
574 }
575
576 l_array: return parse_array(p);
577 l_object: return parse_object(p);
578 l_func: { CONSUME(); return parse_func(p); }
579
580 l_class: {
581 uint32_t class_off = (uint32_t)TOFF;
582 CONSUME();
583 sv_ast_t *cls = parse_class(p);
584 cls->src_off = class_off;
585 return cls;
586 }
587
588 l_async: {
589 uint32_t async_off = (uint32_t)TOFF;
590 CONSUME();
591 bool has_line_term = lookahead_crosses_line_terminator(p);
592 if (!has_line_term && LA() == TOK_FUNC) {
593 NEXT(); CONSUME();
594 sv_ast_t *fn = parse_func(p);
595 fn->flags |= FN_ASYNC;
596 fn->src_off = async_off;
597 return fn;
598 }
599 if (has_line_term) return mk_ident_from_tok(p);
600 sv_ast_t *arrow = try_parse_async_arrow(p);
601 if (arrow) return arrow;
602 return mk_ident_from_tok(p);
603 }
604
605 l_template: {
606 CONSUME();
607 sv_ast_t *n = mk(N_TEMPLATE);
608 const uint8_t *in = (const uint8_t *)&CODE[TOFF];
609 size_t tpl_len = TLEN;
610 size_t i = 1;
611
612 for (;;) {
613 size_t seg_start = i;
614 while (i < tpl_len - 1) {
615 if (in[i] == '\\' && i + 1 < tpl_len - 1) { i += 2; continue; }
616 if (in[i] == '$' && i + 1 < tpl_len - 1 && in[i + 1] == '{') break;
617 i++;
618 }
619 sv_ast_t *s = mk(N_STRING);
620 s->flags |= FN_TEMPLATE_SEGMENT;
621 s->aux = (const char *)&in[seg_start];
622 s->aux_len = (uint32_t)(i - seg_start);
623 sv_tpl_cooked_t cooked = decode_template_segment(p, in, seg_start, i);
624 if (cooked.ok && cooked.valid_cooked) {
625 s->str = cooked.str;
626 s->len = cooked.len;
627 } else if (cooked.ok) s->flags |= FN_INVALID_COOKED;
628
629 sv_ast_list_push(&n->args, s);
630 if (i >= tpl_len - 1 || in[i] != '$') break;
631
632 i += 2;
633 size_t expr_start = i;
634 size_t expr_max_len = (
635 tpl_len > 0 && expr_start < tpl_len - 1)
636 ? (tpl_len - 1 - expr_start) : 0;
637
638 sv_lexer_checkpoint_t cp;
639 sv_lexer_push_source(&p->lx, &cp, (const char *)&in[expr_start], (ant_offset_t)expr_max_len);
640
641 sv_ast_t *expr = parse_expr(p);
642 sv_ast_list_push(&n->args, expr);
643
644 if (NEXT() != TOK_RBRACE) {
645 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Unterminated template expression");
646 sv_lexer_pop_source(&p->lx, &cp);
647 return n;
648 }
649 CONSUME();
650
651 size_t consumed_expr = (size_t)POS;
652 sv_lexer_pop_source(&p->lx, &cp);
653
654 if (consumed_expr == 0) {
655 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Unterminated template expression");
656 return n;
657 } i = expr_start + consumed_expr;
658 }
659 return n;
660 }
661
662 l_new: {
663 CONSUME();
664
665 if (NEXT() == TOK_DOT) {
666 CONSUME();
667 if (NEXT() == TOK_IDENTIFIER && TLEN == 6 && memcmp(tok_str(p), "target", 6) == 0) {
668 CONSUME();
669 return mk(N_NEW_TARGET);
670 }
671 sv_parse_unexpected_token(p);
672 return mk(N_EMPTY);
673 }
674
675 sv_ast_t *n = mk(N_NEW);
676 sv_ast_t *callee = parse_primary(p);
677
678 for (;;) {
679 uint8_t la = NEXT();
680 if (la == TOK_DOT) {
681 CONSUME();
682 NEXT();
683 sv_ast_t *mem = mk(N_MEMBER);
684 mem->left = callee;
685 mem->right = parse_dot_property_name(p);
686 if (!mem->right) return mk(N_EMPTY);
687 callee = mem;
688 } else if (la == TOK_LBRACKET) {
689 CONSUME();
690 sv_ast_t *mem = mk(N_MEMBER);
691 mem->left = callee;
692 mem->right = parse_expr(p);
693 mem->flags = 1;
694 expect(p, TOK_RBRACKET);
695 callee = mem;
696 } else break;
697 }
698 n->left = callee;
699
700 if (NEXT() == TOK_LPAREN) {
701 CONSUME();
702 while (NEXT() != TOK_RPAREN && TOK != TOK_EOF) {
703 if (TOK == TOK_REST) {
704 CONSUME();
705 sv_ast_t *spread = mk(N_SPREAD);
706 spread->right = parse_assign(p);
707 sv_ast_list_push(&n->args, spread);
708 } else sv_ast_list_push(&n->args, parse_assign(p));
709 if (NEXT() == TOK_COMMA) CONSUME();
710 else break;
711 } expect(p, TOK_RPAREN);
712 }
713 return n;
714 }
715
716 l_typeof: {
717 CONSUME();
718 sv_ast_t *n = mk(N_TYPEOF);
719 n->right = parse_unary(p);
720 return n;
721 }
722
723 l_void: {
724 CONSUME();
725 sv_ast_t *n = mk(N_VOID);
726 n->right = parse_unary(p);
727 return n;
728 }
729
730 l_delete: {
731 CONSUME();
732 sv_ast_t *n = mk(N_DELETE);
733 n->right = parse_unary(p);
734 if (p->lx.strict && n->right && n->right->type == N_IDENT) {
735 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "cannot delete bindings in strict mode");
736 return mk(N_EMPTY);
737 }
738 return n;
739 }
740
741 l_yield: {
742 CONSUME();
743 sv_ast_t *n = mk(N_YIELD);
744 if (NEXT() == TOK_MUL) {
745 CONSUME();
746 n->flags = 1;
747 }
748 if (TOK != TOK_SEMICOLON && TOK != TOK_RBRACE &&
749 TOK != TOK_RPAREN && TOK != TOK_RBRACKET &&
750 TOK != TOK_EOF && TOK != TOK_COMMA)
751 n->right = parse_assign(p);
752 return n;
753 }
754
755 l_await: {
756 CONSUME();
757 sv_ast_t *n = mk(N_AWAIT);
758 n->right = parse_unary(p);
759 return n;
760 }
761
762 l_super: {
763 CONSUME();
764 return mk_ident("super", 5);
765 }
766
767 l_spread: {
768 CONSUME();
769 sv_ast_t *n = mk(N_SPREAD);
770 n->right = parse_assign(p);
771 return n;
772 }
773
774 l_import_expr: {
775 CONSUME();
776 if (NEXT() != TOK_LPAREN) return mk_ident("import", 6);
777 CONSUME();
778 sv_ast_t *n = mk(N_IMPORT);
779 n->right = parse_expr(p);
780 expect(p, TOK_RPAREN);
781 return n;
782 }
783
784 l_regex: {
785 CONSUME();
786 ant_offset_t pattern_start = (TOK == TOK_DIV_ASSIGN) ? (TOFF + 1) : POS;
787 if (TOK == TOK_DIV_ASSIGN) POS = pattern_start;
788 bool in_class = false;
789
790 while (POS < CLEN) {
791 char c = CODE[POS];
792 if (c == '\\' && POS + 1 < CLEN) {
793 POS += 2;
794 continue;
795 }
796 if (c == '[') in_class = true;
797 else if (c == ']') in_class = false;
798 else if (c == '/' && !in_class) break;
799 POS++;
800 }
801
802 ant_offset_t pattern_end = POS;
803 if (POS < CLEN) POS++;
804
805 ant_offset_t flags_start = POS;
806 while (POS < CLEN) {
807 char c = CODE[POS];
808 if (
809 c == 'd' || c == 'g' || c == 'i' || c == 'm' ||
810 c == 's' || c == 'u' || c == 'v' || c == 'y') POS++;
811 else break;
812 }
813
814 ant_offset_t flags_end = POS;
815 sv_ast_t *n = mk(N_REGEXP);
816
817 n->str = &CODE[pattern_start];
818 n->len = (uint32_t)(pattern_end - pattern_start);
819 n->aux = &CODE[flags_start];
820 n->aux_len = (uint32_t)(flags_end - flags_start);
821 CONSUMED = 1;
822 return n;
823 }
824
825 l_private_name: {
826 CONSUME();
827 NEXT();
828 if (!is_private_ident_like_tok(TOK)) {
829 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "private field name expected");
830 return mk(N_EMPTY);
831 }
832 sv_ast_t *n = mk_private_ident_from_tok(p);
833 CONSUME();
834 return n;
835 }
836}
837
838static sv_ast_t *parse_array(P) {
839 CONSUME();
840 sv_ast_t *n = mk(N_ARRAY);
841 while (NEXT() != TOK_RBRACKET && TOK != TOK_EOF) {
842 if (TOK == TOK_COMMA) {
843 CONSUME();
844 sv_ast_list_push(&n->args, mk(N_EMPTY));
845 continue;
846 }
847 if (TOK == TOK_REST) {
848 CONSUME();
849 sv_ast_t *spread = mk(N_SPREAD);
850 spread->right = parse_assign(p);
851 sv_ast_list_push(&n->args, spread);
852 } else {
853 sv_ast_list_push(&n->args, parse_assign(p));
854 }
855 if (NEXT() == TOK_COMMA) CONSUME();
856 else break;
857 }
858 expect(p, TOK_RBRACKET);
859 return n;
860}
861
862static sv_ast_t *parse_object(P) {
863 CONSUME();
864 sv_ast_t *n = mk(N_OBJECT);
865 bool proto_set = false;
866 while (NEXT() != TOK_RBRACE && TOK != TOK_EOF) {
867 sv_ast_t *prop = mk(N_PROPERTY);
868
869 if (TOK == TOK_REST) {
870 CONSUME();
871 sv_ast_t *spread = mk(N_SPREAD);
872 spread->right = parse_assign(p);
873 sv_ast_list_push(&n->args, spread);
874 if (NEXT() == TOK_COMMA) CONSUME();
875 continue;
876 }
877
878 if (TOK == TOK_LBRACKET) {
879 CONSUME();
880 prop->left = parse_assign(p);
881 expect(p, TOK_RBRACKET);
882 prop->flags |= FN_COMPUTED;
883 }
884 else if (TOK == TOK_MUL) {
885 prop->flags |= FN_GENERATOR;
886 CONSUME();
887 NEXT();
888
889 if (TOK == TOK_LBRACKET) {
890 CONSUME();
891 prop->left = parse_assign(p);
892 expect(p, TOK_RBRACKET);
893 prop->flags |= FN_COMPUTED;
894 } else if (TOK == TOK_NUMBER) {
895 CONSUME();
896 prop->left = mk_num(tod(TVAL));
897 } else if (TOK == TOK_STRING) {
898 prop->left = mk(N_STRING);
899 sv_ast_set_string(prop->left, sv_lexer_str_literal(&p->lx));
900 CONSUME();
901 } else {
902 prop->left = mk_ident_from_tok(p);
903 CONSUME();
904 }
905
906 prop->right = parse_func(p);
907 prop->right->flags |= FN_GENERATOR | FN_METHOD;
908 prop->right->src_off = prop->src_off;
909 sv_ast_list_push(&n->args, prop);
910 if (NEXT() == TOK_COMMA) CONSUME();
911 continue;
912 }
913 else if (
914 (TLEN == 3 && memcmp(tok_str(p), "get", 3) == 0) ||
915 (TLEN == 3 && memcmp(tok_str(p), "set", 3) == 0)) {
916 uint8_t gs = tok_str(p)[0];
917 uint8_t la = LA();
918 if (la != TOK_COLON && la != TOK_LPAREN && la != TOK_COMMA &&
919 la != TOK_RBRACE) {
920 CONSUME();
921 prop->flags |= (gs == 'g') ? FN_GETTER : FN_SETTER;
922 NEXT();
923
924 if (TOK == TOK_LBRACKET) {
925 CONSUME();
926 prop->left = parse_assign(p);
927 expect(p, TOK_RBRACKET);
928 prop->flags |= FN_COMPUTED;
929 } else if (TOK == TOK_NUMBER) {
930 CONSUME();
931 prop->left = mk_num(tod(TVAL));
932 } else if (TOK == TOK_STRING) {
933 prop->left = mk(N_STRING);
934 sv_ast_set_string(prop->left, sv_lexer_str_literal(&p->lx));
935 CONSUME();
936 } else {
937 prop->left = mk_ident_from_tok(p);
938 CONSUME();
939 }
940
941 prop->right = parse_func(p);
942 prop->right->flags |= FN_METHOD;
943 prop->right->src_off = prop->src_off;
944 sv_ast_list_push(&n->args, prop);
945 if (NEXT() == TOK_COMMA) CONSUME();
946 continue;
947 }
948 prop->left = mk_ident_from_tok(p);
949 CONSUME();
950 }
951 else if (TOK == TOK_ASYNC) {
952 uint8_t la = LA();
953 if (la != TOK_COLON && la != TOK_LPAREN && la != TOK_COMMA && la != TOK_RBRACE) {
954 CONSUME();
955 prop->flags |= FN_ASYNC;
956 NEXT();
957
958 if (TOK == TOK_MUL) {
959 prop->flags |= FN_GENERATOR;
960 CONSUME();
961 NEXT();
962 }
963
964 if (TOK == TOK_LBRACKET) {
965 CONSUME();
966 prop->left = parse_assign(p);
967 expect(p, TOK_RBRACKET);
968 prop->flags |= FN_COMPUTED;
969 } else if (TOK == TOK_NUMBER) {
970 CONSUME();
971 prop->left = mk_num(tod(TVAL));
972 } else if (TOK == TOK_STRING) {
973 prop->left = mk(N_STRING);
974 sv_ast_set_string(prop->left, sv_lexer_str_literal(&p->lx));
975 CONSUME();
976 } else {
977 prop->left = mk_ident_from_tok(p);
978 CONSUME();
979 }
980
981 prop->right = parse_func(p);
982 prop->right->flags |= FN_ASYNC | FN_METHOD;
983 if (prop->flags & FN_GENERATOR)
984 prop->right->flags |= FN_GENERATOR;
985 prop->right->src_off = prop->src_off;
986 sv_ast_list_push(&n->args, prop);
987 if (NEXT() == TOK_COMMA) CONSUME();
988 continue;
989 }
990 prop->left = mk_ident_from_tok(p);
991 CONSUME();
992 }
993 else if (TOK == TOK_NUMBER) {
994 CONSUME();
995 prop->left = mk_num(tod(TVAL));
996 }
997 else if (TOK == TOK_STRING) {
998 prop->left = mk(N_STRING);
999 sv_ast_set_string(prop->left, sv_lexer_str_literal(&p->lx));
1000 CONSUME();
1001 }
1002 else {
1003 prop->left = mk_ident_from_tok(p);
1004 CONSUME();
1005 }
1006
1007 if (NEXT() == TOK_COLON) {
1008 CONSUME();
1009 prop->flags |= FN_COLON;
1010 if (prop->left && prop->left->type == N_IDENT &&
1011 prop->left->len == 9 && memcmp(prop->left->str, "__proto__", 9) == 0) {
1012 if (proto_set) { SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Duplicate __proto__ fields are not allowed in object literals"); return n; }
1013 proto_set = true;
1014 }
1015 prop->right = parse_assign(p);
1016 } else if (TOK == TOK_LPAREN) {
1017 prop->right = parse_func(p);
1018 prop->right->flags |= FN_METHOD;
1019 prop->right->src_off = prop->src_off;
1020 } else {
1021 prop->right = mk_ident(prop->left->str, prop->left->len);
1022 if (NEXT() == TOK_ASSIGN) {
1023 CONSUME();
1024 sv_ast_t *def = mk(N_ASSIGN);
1025 def->op = TOK_ASSIGN;
1026 def->left = prop->right;
1027 def->right = parse_assign(p);
1028 prop->right = def;
1029 }
1030 }
1031
1032 sv_ast_list_push(&n->args, prop);
1033 if (NEXT() == TOK_COMMA) CONSUME();
1034 else break;
1035 }
1036 expect(p, TOK_RBRACE);
1037 return n;
1038}
1039
1040static sv_ast_t *parse_call(P) {
1041 sv_ast_t *n = parse_primary(p);
1042
1043 for (;;) {
1044 uint8_t la = NEXT();
1045 if (la == TOK_LPAREN) {
1046 CONSUME();
1047 sv_ast_t *call = mk(N_CALL);
1048 call->left = n;
1049 while (NEXT() != TOK_RPAREN && TOK != TOK_EOF) {
1050 if (TOK == TOK_REST) {
1051 CONSUME();
1052 sv_ast_t *spread = mk(N_SPREAD);
1053 spread->right = parse_assign(p);
1054 sv_ast_list_push(&call->args, spread);
1055 } else {
1056 sv_ast_list_push(&call->args, parse_assign(p));
1057 }
1058 if (NEXT() == TOK_COMMA) CONSUME();
1059 else break;
1060 }
1061 expect(p, TOK_RPAREN);
1062 n = call;
1063 } else if (la == TOK_DOT) {
1064 CONSUME();
1065 NEXT();
1066 sv_ast_t *mem = mk(N_MEMBER);
1067 mem->left = n;
1068 if (TOK == TOK_HASH) {
1069 CONSUME();
1070 NEXT();
1071 if (!is_private_ident_like_tok(TOK)) {
1072 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "private field name expected");
1073 return mk(N_EMPTY);
1074 }
1075 mem->right = mk_private_ident_from_tok(p);
1076 CONSUME();
1077 } else {
1078 mem->right = parse_dot_property_name(p);
1079 if (!mem->right) return mk(N_EMPTY);
1080 }
1081 n = mem;
1082 } else if (la == TOK_LBRACKET) {
1083 CONSUME();
1084 sv_ast_t *mem = mk(N_MEMBER);
1085 mem->left = n;
1086 mem->right = parse_expr(p);
1087 mem->flags = 1;
1088 expect(p, TOK_RBRACKET);
1089 n = mem;
1090 } else if (la == TOK_OPTIONAL_CHAIN) {
1091 CONSUME();
1092 sv_ast_t *opt = mk(N_OPTIONAL);
1093 opt->left = n;
1094 if (NEXT() == TOK_LBRACKET) {
1095 CONSUME();
1096 opt->right = parse_expr(p);
1097 opt->flags = 1;
1098 expect(p, TOK_RBRACKET);
1099 } else if (TOK == TOK_LPAREN) {
1100 sv_ast_t *call = mk(N_CALL);
1101 call->left = opt;
1102 CONSUME();
1103 while (NEXT() != TOK_RPAREN && TOK != TOK_EOF) {
1104 sv_ast_list_push(&call->args, parse_assign(p));
1105 if (NEXT() == TOK_COMMA) CONSUME();
1106 else break;
1107 }
1108 expect(p, TOK_RPAREN);
1109 n = call;
1110 continue;
1111 } else if (TOK == TOK_HASH) {
1112 CONSUME();
1113 NEXT();
1114 if (!is_private_ident_like_tok(TOK)) {
1115 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "private field name expected");
1116 return mk(N_EMPTY);
1117 }
1118 opt->right = mk_private_ident_from_tok(p);
1119 CONSUME();
1120 } else {
1121 opt->right = parse_dot_property_name(p);
1122 if (!opt->right) return mk(N_EMPTY);
1123 }
1124 n = opt;
1125 } else if (la == TOK_TEMPLATE) {
1126 sv_ast_t *tagged = mk(N_TAGGED_TEMPLATE);
1127 tagged->left = n;
1128 tagged->right = parse_primary(p);
1129 n = tagged;
1130 } else break;
1131 }
1132 return n;
1133}
1134
1135static sv_ast_t *parse_postfix(P) {
1136 sv_ast_t *n = parse_call(p);
1137 uint8_t la = NEXT();
1138 if ((la == TOK_POSTINC || la == TOK_POSTDEC) && !HAD_NEWLINE) {
1139 if (sv_is_strict_restricted_assign_target(p, n)) {
1140 SV_MKERR_TYPED(
1141 JS, JS_ERR_SYNTAX,
1142 "cannot modify eval or arguments in strict mode");
1143 return mk(N_EMPTY);
1144 }
1145 CONSUME();
1146 sv_ast_t *u = mk(N_UPDATE);
1147 u->op = la;
1148 u->right = n;
1149 return u;
1150 }
1151 return n;
1152}
1153
1154static sv_ast_t *parse_unary(P) {
1155 uint8_t la = NEXT();
1156 if (la == TOK_NOT || la == TOK_TILDA ||
1157 la == TOK_UPLUS || la == TOK_UMINUS ||
1158 la == TOK_PLUS || la == TOK_MINUS) {
1159 CONSUME();
1160 sv_ast_t *n = mk(N_UNARY);
1161 n->op = (la == TOK_PLUS) ? TOK_UPLUS :
1162 (la == TOK_MINUS) ? TOK_UMINUS : la;
1163 n->right = parse_unary(p);
1164 if (NEXT() == TOK_EXP) {
1165 SV_MKERR_TYPED(
1166 JS, JS_ERR_SYNTAX,
1167 "Unary operator used immediately before exponentiation expression. "
1168 "Parenthesis must be used to disambiguate operator precedence");
1169 return mk(N_EMPTY);
1170 }
1171 return n;
1172 }
1173 if (la == TOK_POSTINC || la == TOK_POSTDEC) {
1174 CONSUME();
1175 sv_ast_t *target = parse_unary(p);
1176 if (sv_is_strict_restricted_assign_target(p, target)) {
1177 SV_MKERR_TYPED(
1178 JS, JS_ERR_SYNTAX,
1179 "cannot modify eval or arguments in strict mode");
1180 return mk(N_EMPTY);
1181 }
1182 sv_ast_t *n = mk(N_UPDATE);
1183 n->op = la;
1184 n->right = target;
1185 n->flags = 1;
1186 return n;
1187 }
1188 if (la == TOK_THROW) {
1189 CONSUME();
1190 sv_ast_t *n = mk(N_THROW);
1191 n->right = parse_assign(p);
1192 return n;
1193 }
1194 return parse_postfix(p);
1195}
1196
1197static sv_ast_t *parse_binary(P, int min_prec) {
1198 sv_ast_t *left = parse_unary(p);
1199
1200 for (;;) {
1201 uint8_t op = NEXT();
1202 if (op >= TOK_MAX) break;
1203 if (op == TOK_IN && p->no_in) break;
1204 int prec = prec_table[op];
1205 if (prec == 0 || prec < min_prec) break;
1206 CONSUME();
1207 int next_prec = (op == TOK_EXP) ? prec : prec + 1;
1208 sv_ast_t *right = parse_binary(p, next_prec);
1209 sv_ast_t *bin = mk(N_BINARY);
1210 bin->op = op;
1211 bin->left = left;
1212 bin->right = right;
1213 left = bin;
1214 }
1215 return left;
1216}
1217
1218static sv_ast_t *parse_ternary(P) {
1219 sv_ast_t *cond = parse_binary(p, 1);
1220 if (NEXT() == TOK_Q) {
1221 CONSUME();
1222 sv_ast_t *n = mk(N_TERNARY);
1223 n->cond = cond;
1224 n->left = parse_assign(p);
1225 expect(p, TOK_COLON);
1226 n->right = parse_assign(p);
1227 return n;
1228 }
1229 return cond;
1230}
1231
1232static bool is_assign_op(uint8_t tok) {
1233 return tok >= TOK_ASSIGN && tok <= TOK_NULLISH_ASSIGN;
1234}
1235
1236static sv_ast_t *parse_assign(P) {
1237 sv_ast_t *left = parse_ternary(p);
1238 uint8_t op = NEXT();
1239 if (op == TOK_ARROW) {
1240 CONSUME();
1241 sv_ast_t *fn = mk(N_FUNC);
1242 fn->flags = FN_ARROW;
1243 fn->src_off = left->src_off;
1244 if (left->type == N_IDENT) {
1245 sv_ast_list_push(&fn->args, left);
1246 } else if (left->flags & FN_PAREN) {
1247 if (left->type != N_UNDEF)
1248 push_arrow_params_from_expr(fn, left);
1249 } else {
1250 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Malformed arrow function parameter list");
1251 return mk(N_EMPTY);
1252 }
1253 fn->body = parse_arrow_body(p);
1254 fn->src_end = node_src_end(p, fn->body);
1255 return fn;
1256 }
1257 if (is_assign_op(op)) {
1258 if (left->type == N_NEW_TARGET) {
1259 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Invalid left-hand side in assignment");
1260 return mk(N_EMPTY);
1261 }
1262 if ((left->flags & FN_PAREN) && op == TOK_ASSIGN &&
1263 (left->type == N_OBJECT || left->type == N_OBJECT_PAT ||
1264 left->type == N_ARRAY || left->type == N_ARRAY_PAT)) {
1265 SV_MKERR_TYPED(
1266 JS, JS_ERR_SYNTAX,
1267 "Invalid destructuring assignment target");
1268 return mk(N_EMPTY);
1269 }
1270 if (sv_is_strict_restricted_assign_target(p, left)) {
1271 SV_MKERR_TYPED(
1272 JS, JS_ERR_SYNTAX,
1273 "cannot modify eval or arguments in strict mode");
1274 return mk(N_EMPTY);
1275 }
1276 CONSUME();
1277 sv_ast_t *n = mk(N_ASSIGN);
1278 n->op = op;
1279 n->left = left;
1280 n->right = parse_assign(p);
1281 return n;
1282 }
1283 return left;
1284}
1285
1286static sv_ast_t *parse_expr(P) {
1287 sv_ast_t *left = parse_assign(p);
1288 while (NEXT() == TOK_COMMA) {
1289 CONSUME();
1290 sv_ast_t *n = mk(N_SEQUENCE);
1291 n->left = left;
1292 n->right = parse_assign(p);
1293 left = n;
1294 }
1295 return left;
1296}
1297
1298static sv_ast_t *parse_paren_expr(P) {
1299 sv_ast_t *left = parse_assign(p);
1300 while (NEXT() == TOK_COMMA) {
1301 CONSUME();
1302 if (NEXT() == TOK_RPAREN && LA() == TOK_ARROW) break;
1303
1304 sv_ast_t *n = mk(N_SEQUENCE);
1305 n->left = left;
1306 n->right = parse_assign(p);
1307 left = n;
1308 }
1309 return left;
1310}
1311
1312bool ast_references_arguments(const sv_ast_t *node) {
1313 if (!node) return false;
1314 if (node->type == N_IDENT && node->len == 9 && memcmp(node->str, "arguments", 9) == 0)
1315 return true;
1316
1317 if (node->type == N_FUNC && !(node->flags & FN_ARROW)) {
1318 for (int i = 0; i < node->args.count; i++)
1319 if (ast_references_arguments(node->args.items[i])) return true;
1320 return false;
1321 }
1322
1323 if (ast_references_arguments(node->left)) return true;
1324 if (ast_references_arguments(node->right)) return true;
1325 if (ast_references_arguments(node->body)) return true;
1326 if (ast_references_arguments(node->catch_body)) return true;
1327 if (ast_references_arguments(node->finally_body)) return true;
1328 for (int i = 0; i < node->args.count; i++)
1329 if (ast_references_arguments(node->args.items[i])) return true;
1330
1331 return false;
1332}
1333
1334static bool ast_references_new_target(const sv_ast_t *node) {
1335 if (!node) return false;
1336 if (node->type == N_NEW_TARGET) return true;
1337 if (node->type == N_FUNC && !(node->flags & FN_ARROW)) return false;
1338
1339 if (ast_references_new_target(node->left)) return true;
1340 if (ast_references_new_target(node->right)) return true;
1341 if (ast_references_new_target(node->cond)) return true;
1342 if (ast_references_new_target(node->body)) return true;
1343 if (ast_references_new_target(node->catch_body)) return true;
1344 if (ast_references_new_target(node->finally_body)) return true;
1345 if (ast_references_new_target(node->catch_param)) return true;
1346 if (ast_references_new_target(node->init)) return true;
1347 if (ast_references_new_target(node->update)) return true;
1348
1349 for (int i = 0; i < node->args.count; i++)
1350 if (ast_references_new_target(node->args.items[i])) return true;
1351
1352 return false;
1353}
1354
1355static sv_ast_t *parse_func(P) {
1356 sv_ast_t *fn = mk(N_FUNC);
1357
1358 if (NEXT() == TOK_MUL) {
1359 CONSUME();
1360 fn->flags |= FN_GENERATOR;
1361 }
1362
1363 if (is_ident_like_tok(NEXT())) {
1364 fn->str = tok_ident_str(p, &fn->len);
1365 sv_strict_check_binding_ident(p, fn->str, fn->len);
1366 CONSUME();
1367 }
1368
1369 expect(p, TOK_LPAREN);
1370 while (NEXT() != TOK_RPAREN && TOK != TOK_EOF) {
1371 if (TOK == TOK_REST) {
1372 CONSUME();
1373 sv_ast_t *rest = mk(N_REST);
1374 rest->right = parse_binding_pattern(p);
1375 sv_ast_list_push(&fn->args, rest);
1376 break;
1377 }
1378 sv_ast_t *param = parse_binding_pattern(p);
1379 if (NEXT() == TOK_ASSIGN) {
1380 CONSUME();
1381 sv_ast_t *def = mk(N_ASSIGN_PAT);
1382 def->left = param;
1383 def->right = parse_assign(p);
1384 param = def;
1385 }
1386 sv_ast_list_push(&fn->args, param);
1387 if (NEXT() == TOK_COMMA) {
1388 CONSUME();
1389 if (NEXT() == TOK_RPAREN) break;
1390 } else break;
1391 }
1392 expect(p, TOK_RPAREN);
1393
1394 fn->body = parse_block(p, true);
1395 fn->src_end = (uint32_t)(TOFF + TLEN);
1396 if (!(fn->flags & FN_ARROW) && ast_references_arguments(fn->body))
1397 fn->flags |= FN_USES_ARGS;
1398 if (!(fn->flags & FN_ARROW) && ast_references_new_target(fn->body))
1399 fn->flags |= FN_USES_NEW_TARGET;
1400 return fn;
1401}
1402
1403static sv_ast_t *parse_class(P) {
1404 sv_ast_t *cls = mk(N_CLASS);
1405
1406 if (is_ident_like_tok(NEXT()) &&
1407 !(TLEN == 7 && memcmp(tok_str(p), "extends", 7) == 0)) {
1408 cls->str = tok_ident_str(p, &cls->len);
1409 CONSUME();
1410 }
1411
1412 if (NEXT() == TOK_IDENTIFIER && TLEN == 7 && memcmp(tok_str(p), "extends", 7) == 0) {
1413 CONSUME();
1414 cls->left = parse_assign(p);
1415 }
1416
1417 expect(p, TOK_LBRACE);
1418 while (NEXT() != TOK_RBRACE && TOK != TOK_EOF) {
1419 if (TOK == TOK_SEMICOLON) { CONSUME(); continue; }
1420
1421 uint8_t flags = 0;
1422
1423 if (
1424 TOK == TOK_STATIC &&
1425 LA() != TOK_LPAREN &&
1426 LA() != TOK_ASSIGN &&
1427 LA() != TOK_SEMICOLON &&
1428 LA() != TOK_RBRACE
1429 ) {
1430 flags |= FN_STATIC;
1431 CONSUME();
1432 NEXT();
1433
1434 if (TOK == TOK_LBRACE) {
1435 sv_ast_t *block = parse_block(p, false);
1436 block->type = N_STATIC_BLOCK;
1437 block->flags = FN_STATIC;
1438 sv_ast_list_push(&cls->args, block);
1439 continue;
1440 }
1441 }
1442
1443 sv_ast_t *method = mk(N_METHOD);
1444 uint32_t method_src_off = (uint32_t)TOFF;
1445
1446 if (TOK == TOK_ASYNC && LA() != TOK_LPAREN) {
1447 flags |= FN_ASYNC;
1448 CONSUME();
1449 NEXT();
1450 }
1451
1452 if (TOK == TOK_MUL) {
1453 flags |= FN_GENERATOR;
1454 CONSUME();
1455 NEXT();
1456 }
1457
1458 if ((TLEN == 3 && memcmp(tok_str(p), "get", 3) == 0) ||
1459 (TLEN == 3 && memcmp(tok_str(p), "set", 3) == 0)) {
1460 uint8_t la = LA();
1461 if (la != TOK_LPAREN && la != TOK_ASSIGN && la != TOK_SEMICOLON && la != TOK_RBRACE) {
1462 flags |= (tok_str(p)[0] == 'g') ? FN_GETTER : FN_SETTER;
1463 CONSUME();
1464 NEXT();
1465 }
1466 }
1467
1468 if (TOK == TOK_LBRACKET) {
1469 CONSUME();
1470 method->left = parse_assign(p);
1471 expect(p, TOK_RBRACKET);
1472 flags |= FN_COMPUTED;
1473 } else if (TOK == TOK_HASH) {
1474 CONSUME();
1475 NEXT();
1476 if (!is_private_ident_like_tok(TOK)) {
1477 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "private field name expected");
1478 return mk(N_EMPTY);
1479 }
1480 method->left = mk_private_ident_from_tok(p);
1481 CONSUME();
1482 } else {
1483 method->left = mk_ident_from_tok(p);
1484 CONSUME();
1485 }
1486
1487 method->flags = flags;
1488
1489 if (!(flags & FN_STATIC) && (flags & FN_GENERATOR) &&
1490 method->left && method->left->type == N_IDENT &&
1491 method->left->len == 11 &&
1492 memcmp(method->left->str, "constructor", 11) == 0) {
1493 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Class constructor may not be a generator");
1494 return cls;
1495 }
1496
1497 if (NEXT() == TOK_LPAREN) {
1498 method->right = parse_func(p);
1499 method->right->flags |= (flags & (FN_ASYNC | FN_GENERATOR)) | FN_METHOD;
1500 method->right->src_off = method_src_off;
1501 } else if (TOK == TOK_ASSIGN) {
1502 CONSUME();
1503 method->right = parse_assign(p);
1504 if (NEXT() == TOK_SEMICOLON) CONSUME();
1505 } else {
1506 method->right = mk(N_UNDEF);
1507 if (TOK == TOK_SEMICOLON) CONSUME();
1508 }
1509
1510 sv_ast_list_push(&cls->args, method);
1511 }
1512 expect(p, TOK_RBRACE);
1513 cls->src_end = (uint32_t)(TOFF + TLEN);
1514 return cls;
1515}
1516
1517static sv_ast_t *parse_block(P, bool directive_ctx) {
1518 expect(p, TOK_LBRACE);
1519 sv_ast_t *block = mk(N_BLOCK);
1520 sv_parse_stmt_list(p, &block->args, true, directive_ctx);
1521 if (JS->thrown_exists) return block;
1522 expect(p, TOK_RBRACE);
1523 return block;
1524}
1525
1526static sv_ast_t *parse_var_decl(P, sv_var_kind_t kind, bool allow_uninit_const) {
1527 sv_ast_t *var = mk(N_VAR);
1528 var->var_kind = kind;
1529
1530 do {
1531 NEXT();
1532 sv_ast_t *decl = mk(N_VARDECL);
1533
1534 if (TOK == TOK_LBRACKET) {
1535 decl->left = parse_array(p);
1536 } else if (TOK == TOK_LBRACE) {
1537 decl->left = parse_object(p);
1538 } else if (TOK == TOK_ERR) {
1539 sv_parse_unexpected_token(p);
1540 return var;
1541 } else {
1542 decl->left = mk_ident_from_tok(p);
1543 sv_strict_check_binding_ident(p, decl->left->str, decl->left->len);
1544 CONSUME();
1545 }
1546 if (NEXT() == TOK_ASSIGN) {
1547 CONSUME();
1548 decl->right = parse_assign(p);
1549 } else if ((kind == SV_VAR_CONST || kind == SV_VAR_USING || kind == SV_VAR_AWAIT_USING) && !allow_uninit_const) {
1550 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Missing initializer in const declaration");
1551 }
1552 sv_ast_list_push(&var->args, decl);
1553 } while (NEXT() == TOK_COMMA && (CONSUME(), 1));
1554
1555 return var;
1556}
1557
1558static sv_ast_t *skip_import_stmt(P) {
1559 while (NEXT() != TOK_SEMICOLON && TOK != TOK_EOF) CONSUME();
1560 if (TOK == TOK_SEMICOLON) CONSUME();
1561 return mk(N_EMPTY);
1562}
1563
1564enum {
1565 IMPORT_BIND_DEFAULT = 1 << 0,
1566 IMPORT_BIND_NAMESPACE = 1 << 1,
1567};
1568
1569static inline void import_decl_add_binding(
1570 sv_ast_t *decl,
1571 const char *import_name, uint32_t import_len,
1572 const char *local_name, uint32_t local_len,
1573 uint8_t flags
1574) {
1575 sv_ast_t *spec = mk_plain(N_IMPORT_SPEC);
1576 spec->flags = flags;
1577 if (import_name)
1578 spec->left = mk_ident(import_name, import_len);
1579 spec->right = mk_ident(local_name, local_len);
1580 sv_ast_list_push(&decl->args, spec);
1581}
1582
1583static sv_ast_t *parse_import_stmt(P) {
1584 static const char default_name[] = "default";
1585 sv_ast_t *decl = mk(N_IMPORT_DECL);
1586
1587 if (NEXT() == TOK_STRING) {
1588 sv_ast_t *spec = mk(N_STRING);
1589 sv_ast_set_string(spec, sv_lexer_str_literal(&p->lx));
1590 CONSUME();
1591 if (NEXT() == TOK_SEMICOLON) CONSUME();
1592 decl->right = spec;
1593 return decl;
1594 }
1595
1596 bool saw_clause = false;
1597
1598 if (is_ident_like_tok(NEXT())) {
1599 saw_clause = true;
1600 uint32_t local_len = 0;
1601 const char *local_name = tok_ident_str(p, &local_len);
1602 import_decl_add_binding(
1603 decl,
1604 default_name, (uint32_t)(sizeof(default_name) - 1),
1605 local_name, local_len,
1606 IMPORT_BIND_DEFAULT
1607 );
1608 CONSUME();
1609 if (NEXT() == TOK_COMMA) CONSUME();
1610 else goto parse_from;
1611 }
1612
1613 if (NEXT() == TOK_MUL) {
1614 saw_clause = true;
1615 CONSUME();
1616 expect(p, TOK_AS);
1617 NEXT();
1618 if (!is_ident_like_tok(TOK)) return skip_import_stmt(p);
1619 uint32_t ns_len = 0;
1620 const char *ns_name = tok_ident_str(p, &ns_len);
1621 import_decl_add_binding(
1622 decl,
1623 NULL, 0,
1624 ns_name, ns_len,
1625 IMPORT_BIND_NAMESPACE
1626 );
1627 CONSUME();
1628 } else if (NEXT() == TOK_LBRACE) {
1629 saw_clause = true;
1630 CONSUME();
1631 while (NEXT() != TOK_RBRACE && TOK != TOK_EOF) {
1632 const char *import_name;
1633 uint32_t import_len;
1634
1635 if (TOK == TOK_STRING) {
1636 sv_lex_string_t s = sv_lexer_str_literal(&p->lx);
1637 import_name = s.str;
1638 import_len = s.len;
1639 CONSUME();
1640 } else if (!(TOK >= TOK_IDENTIFIER && TOK < TOK_IDENT_LIKE_END)) {
1641 CONSUME();
1642 continue;
1643 } else {
1644 import_name = tok_ident_str(p, &import_len);
1645 CONSUME();
1646 }
1647
1648 const char *local_name = import_name;
1649 uint32_t local_len = import_len;
1650
1651 if (NEXT() == TOK_AS) {
1652 CONSUME();
1653 NEXT();
1654 if (!is_ident_like_tok(TOK)) return skip_import_stmt(p);
1655 local_name = tok_ident_str(p, &local_len);
1656 CONSUME();
1657 }
1658
1659 import_decl_add_binding(decl, import_name, import_len, local_name, local_len, 0);
1660
1661 if (NEXT() == TOK_COMMA) {
1662 CONSUME();
1663 if (NEXT() == TOK_RBRACE) break;
1664 }
1665 }
1666 expect(p, TOK_RBRACE);
1667 }
1668
1669parse_from:
1670 if (!saw_clause) return skip_import_stmt(p);
1671 expect(p, TOK_FROM);
1672 if (NEXT() != TOK_STRING) return skip_import_stmt(p);
1673
1674 sv_ast_t *spec = mk(N_STRING);
1675 sv_ast_set_string(spec, sv_lexer_str_literal(&p->lx));
1676 CONSUME();
1677 decl->right = spec;
1678
1679 if (NEXT() == TOK_SEMICOLON) CONSUME();
1680 return decl;
1681}
1682
1683static sv_ast_t *parse_export_name(P) {
1684 NEXT();
1685 if (TOK == TOK_STRING) {
1686 sv_lex_string_t s = sv_lexer_str_literal(&p->lx);
1687 sv_ast_t *name = mk(N_IDENT);
1688 name->str = s.str;
1689 name->len = s.len;
1690 CONSUME();
1691 return name;
1692 }
1693
1694 if (!(TOK >= TOK_IDENTIFIER && TOK < TOK_IDENT_LIKE_END)) {
1695 sv_parse_unexpected_token(p);
1696 return NULL;
1697 }
1698 sv_ast_t *name = mk_ident_from_tok(p);
1699 CONSUME();
1700 return name;
1701}
1702
1703static sv_ast_t *parse_export_stmt(P) {
1704 sv_ast_t *decl = mk(N_EXPORT);
1705 NEXT();
1706
1707 if (TOK == TOK_DEFAULT) {
1708 CONSUME();
1709 decl->flags |= EX_DEFAULT;
1710
1711 if (NEXT() == TOK_ASYNC && LA() == TOK_FUNC && !lookahead_crosses_line_terminator(p)) {
1712 uint32_t async_off = (uint32_t)TOFF;
1713 CONSUME();
1714 NEXT(); CONSUME();
1715 decl->left = parse_func(p);
1716 decl->left->flags |= FN_ASYNC;
1717 decl->left->src_off = async_off;
1718 if (NEXT() == TOK_SEMICOLON) CONSUME();
1719 return decl;
1720 }
1721 if (TOK == TOK_FUNC) {
1722 CONSUME();
1723 decl->left = parse_func(p);
1724 if (NEXT() == TOK_SEMICOLON) CONSUME();
1725 return decl;
1726 }
1727 if (TOK == TOK_CLASS) {
1728 uint32_t class_off = (uint32_t)TOFF;
1729 CONSUME();
1730 decl->left = parse_class(p);
1731 decl->left->src_off = class_off;
1732 if (NEXT() == TOK_SEMICOLON) CONSUME();
1733 return decl;
1734 }
1735
1736 decl->left = parse_assign(p);
1737 if (NEXT() == TOK_SEMICOLON) CONSUME();
1738 return decl;
1739 }
1740
1741 if (TOK == TOK_ASYNC && LA() == TOK_FUNC && !lookahead_crosses_line_terminator(p)) {
1742 decl->flags |= EX_DECL;
1743 uint32_t async_off = (uint32_t)TOFF;
1744 CONSUME();
1745 NEXT(); CONSUME();
1746 decl->left = parse_func(p);
1747 decl->left->flags |= FN_ASYNC;
1748 decl->left->src_off = async_off;
1749 if (!decl->left->str || decl->left->len == 0)
1750 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "exported function declarations require a name");
1751 return decl;
1752 }
1753
1754 if (TOK == TOK_FUNC) {
1755 decl->flags |= EX_DECL;
1756 CONSUME();
1757 decl->left = parse_func(p);
1758 if (!decl->left->str || decl->left->len == 0)
1759 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "exported function declarations require a name");
1760 return decl;
1761 }
1762 if (TOK == TOK_CLASS) {
1763 decl->flags |= EX_DECL;
1764 uint32_t class_off = (uint32_t)TOFF;
1765 CONSUME();
1766 decl->left = parse_class(p);
1767 decl->left->src_off = class_off;
1768 if (!decl->left->str || decl->left->len == 0)
1769 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "exported class declarations require a name");
1770 return decl;
1771 }
1772
1773 if (TOK == TOK_VAR || TOK == TOK_LET || TOK == TOK_CONST) {
1774 decl->flags |= EX_DECL;
1775 sv_var_kind_t kind = (
1776 TOK == TOK_VAR) ? SV_VAR_VAR :
1777 (TOK == TOK_LET) ? SV_VAR_LET : SV_VAR_CONST;
1778 CONSUME();
1779 decl->left = parse_var_decl(p, kind, false);
1780 if (NEXT() == TOK_SEMICOLON) CONSUME();
1781 return decl;
1782 }
1783
1784 if (TOK == TOK_LBRACE) {
1785 decl->flags |= EX_NAMED;
1786 CONSUME();
1787 while (NEXT() != TOK_RBRACE && TOK != TOK_EOF) {
1788 sv_ast_t *local_name = parse_export_name(p);
1789 if (!local_name) return decl;
1790
1791 sv_ast_t *export_name = local_name;
1792 if (NEXT() == TOK_AS) {
1793 CONSUME();
1794 export_name = parse_export_name(p);
1795 if (!export_name) return decl;
1796 }
1797
1798 sv_ast_t *spec = mk(N_IMPORT_SPEC);
1799 spec->left = local_name;
1800 spec->right = export_name;
1801 sv_ast_list_push(&decl->args, spec);
1802
1803 if (NEXT() == TOK_COMMA) {
1804 CONSUME();
1805 if (NEXT() == TOK_RBRACE) break;
1806 } else {
1807 break;
1808 }
1809 }
1810 expect(p, TOK_RBRACE);
1811
1812 if (NEXT() == TOK_FROM) {
1813 CONSUME();
1814 if (NEXT() != TOK_STRING) {
1815 sv_parse_unexpected_token(p);
1816 return decl;
1817 }
1818 sv_ast_t *spec = mk(N_STRING);
1819 sv_ast_set_string(spec, sv_lexer_str_literal(&p->lx));
1820 decl->right = spec;
1821 decl->flags |= EX_FROM;
1822 CONSUME();
1823 }
1824
1825 if (NEXT() == TOK_SEMICOLON) CONSUME();
1826 return decl;
1827 }
1828
1829 if (TOK == TOK_MUL) {
1830 decl->flags |= EX_STAR;
1831 CONSUME();
1832
1833 if (NEXT() == TOK_AS) {
1834 decl->flags |= EX_NAMESPACE;
1835 CONSUME();
1836
1837 sv_ast_t *name = parse_export_name(p);
1838 if (!name) return decl;
1839
1840 sv_ast_t *spec = mk(N_IMPORT_SPEC);
1841 spec->right = name;
1842 sv_ast_list_push(&decl->args, spec);
1843 }
1844
1845 expect(p, TOK_FROM);
1846 if (NEXT() != TOK_STRING) {
1847 sv_parse_unexpected_token(p);
1848 return decl;
1849 }
1850 sv_ast_t *spec = mk(N_STRING);
1851 sv_ast_set_string(spec, sv_lexer_str_literal(&p->lx));
1852 decl->right = spec;
1853 decl->flags |= EX_FROM;
1854 CONSUME();
1855
1856 if (NEXT() == TOK_SEMICOLON) CONSUME();
1857 return decl;
1858 }
1859
1860 sv_parse_unexpected_token(p);
1861 return decl;
1862}
1863
1864static sv_ast_t *parse_stmt(P) {
1865 NEXT();
1866
1867 static const void *dispatch[TOK_MAX] = {
1868 [TOK_SEMICOLON] = &&l_semi,
1869 [TOK_LBRACE] = &&l_block,
1870 [TOK_VAR] = &&l_var,
1871 [TOK_LET] = &&l_let,
1872 [TOK_CONST] = &&l_const,
1873 [TOK_IF] = &&l_if,
1874 [TOK_WHILE] = &&l_while,
1875 [TOK_DO] = &&l_do,
1876 [TOK_FOR] = &&l_for,
1877 [TOK_RETURN] = &&l_return,
1878 [TOK_THROW] = &&l_throw,
1879 [TOK_BREAK] = &&l_break,
1880 [TOK_CONTINUE] = &&l_continue,
1881 [TOK_TRY] = &&l_try,
1882 [TOK_SWITCH] = &&l_switch,
1883 [TOK_DEBUGGER] = &&l_debugger,
1884 [TOK_WITH] = &&l_with,
1885 [TOK_FUNC] = &&l_func,
1886 [TOK_CLASS] = &&l_class,
1887 [TOK_ASYNC] = &&l_async,
1888 [TOK_EXPORT] = &&l_export,
1889 [TOK_IMPORT] = &&l_import,
1890 };
1891
1892 if (TOK == TOK_USING) {
1893 CONSUME();
1894 sv_ast_t *n = parse_var_decl(p, SV_VAR_USING, false);
1895 if (NEXT() == TOK_SEMICOLON) CONSUME();
1896 return n;
1897 }
1898
1899 if (TOK == TOK_AWAIT) {
1900 sv_lexer_state_t saved;
1901 sv_lexer_save_state(&p->lx, &saved);
1902 CONSUME();
1903 NEXT();
1904 if (TOK == TOK_USING) {
1905 CONSUME();
1906 sv_ast_t *n = parse_var_decl(p, SV_VAR_AWAIT_USING, false);
1907 if (NEXT() == TOK_SEMICOLON) CONSUME();
1908 return n;
1909 }
1910 sv_lexer_restore_state(&p->lx, &saved);
1911 }
1912
1913 if (TOK < TOK_MAX && dispatch[TOK])
1914 goto *dispatch[TOK];
1915 goto l_expr_stmt;
1916
1917 l_semi: { CONSUME(); return mk(N_EMPTY); }
1918 l_block: return parse_block(p, false);
1919
1920 l_var: {
1921 CONSUME();
1922 sv_ast_t *n = parse_var_decl(p, SV_VAR_VAR, false);
1923 if (NEXT() == TOK_SEMICOLON) CONSUME();
1924 return n;
1925 }
1926 l_let: {
1927 CONSUME();
1928 sv_ast_t *n = parse_var_decl(p, SV_VAR_LET, false);
1929 if (NEXT() == TOK_SEMICOLON) CONSUME();
1930 return n;
1931 }
1932 l_const: {
1933 CONSUME();
1934 sv_ast_t *n = parse_var_decl(p, SV_VAR_CONST, false);
1935 if (NEXT() == TOK_SEMICOLON) CONSUME();
1936 return n;
1937 }
1938
1939 l_if: {
1940 CONSUME();
1941 sv_ast_t *n = mk(N_IF);
1942 expect(p, TOK_LPAREN);
1943 n->cond = parse_expr(p);
1944 expect(p, TOK_RPAREN);
1945 n->left = parse_stmt(p);
1946 if (NEXT() == TOK_ELSE) {
1947 CONSUME();
1948 n->right = parse_stmt(p);
1949 }
1950 return n;
1951 }
1952
1953 l_while: {
1954 CONSUME();
1955 sv_ast_t *n = mk(N_WHILE);
1956 expect(p, TOK_LPAREN);
1957 n->cond = parse_expr(p);
1958 expect(p, TOK_RPAREN);
1959 n->body = parse_stmt(p);
1960 return n;
1961 }
1962
1963 l_do: {
1964 CONSUME();
1965 sv_ast_t *n = mk(N_DO_WHILE);
1966 n->body = parse_stmt(p);
1967 expect(p, TOK_WHILE);
1968 expect(p, TOK_LPAREN);
1969 n->cond = parse_expr(p);
1970 expect(p, TOK_RPAREN);
1971 if (NEXT() == TOK_SEMICOLON) CONSUME();
1972 return n;
1973 }
1974
1975 l_for: {
1976 CONSUME();
1977 bool is_for_await = false;
1978 if (NEXT() == TOK_AWAIT) {
1979 CONSUME();
1980 is_for_await = true;
1981 }
1982 expect(p, TOK_LPAREN);
1983 sv_ast_t *init_node = NULL;
1984
1985 NEXT();
1986 if (TOK == TOK_AWAIT) {
1987 sv_lexer_state_t saved;
1988 sv_lexer_save_state(&p->lx, &saved);
1989 CONSUME();
1990 NEXT();
1991 if (TOK == TOK_USING) {
1992 CONSUME();
1993 p->no_in = true;
1994 init_node = parse_var_decl(p, SV_VAR_AWAIT_USING, true);
1995 p->no_in = false;
1996 } else sv_lexer_restore_state(&p->lx, &saved);
1997 }
1998
1999 if (!init_node && TOK == TOK_USING) {
2000 CONSUME();
2001 p->no_in = true;
2002 init_node = parse_var_decl(p, SV_VAR_USING, true);
2003 p->no_in = false;
2004 } else if (!init_node && (TOK == TOK_VAR || TOK == TOK_LET || TOK == TOK_CONST)) {
2005 sv_var_kind_t kind = (
2006 TOK == TOK_VAR) ? SV_VAR_VAR :
2007 (TOK == TOK_LET) ? SV_VAR_LET : SV_VAR_CONST;
2008 CONSUME();
2009 p->no_in = true;
2010 init_node = parse_var_decl(p, kind, true);
2011 p->no_in = false;
2012 } else if (!init_node && TOK != TOK_SEMICOLON) {
2013 p->no_in = true;
2014 init_node = parse_expr(p);
2015 p->no_in = false;
2016 }
2017
2018 uint8_t la = NEXT();
2019 if (la == TOK_IN) {
2020 CONSUME();
2021 sv_ast_t *n = mk(N_FOR_IN);
2022 n->left = init_node;
2023 n->right = parse_expr(p);
2024 expect(p, TOK_RPAREN);
2025 n->body = parse_stmt(p);
2026 return n;
2027 }
2028 if (la == TOK_OF || (la == TOK_IDENTIFIER && TLEN == 2 &&
2029 memcmp(tok_str(p), "of", 2) == 0)) {
2030 CONSUME();
2031 sv_ast_t *n = mk(is_for_await ? N_FOR_AWAIT_OF : N_FOR_OF);
2032 n->left = init_node;
2033 n->right = parse_assign(p);
2034 expect(p, TOK_RPAREN);
2035 n->body = parse_stmt(p);
2036 return n;
2037 }
2038
2039 if (init_node && init_node->type == N_VAR && (
2040 init_node->var_kind == SV_VAR_CONST ||
2041 init_node->var_kind == SV_VAR_USING ||
2042 init_node->var_kind == SV_VAR_AWAIT_USING)) {
2043 for (int i = 0; i < init_node->args.count; i++) {
2044 sv_ast_t *decl = init_node->args.items[i];
2045 if (decl && decl->type == N_VARDECL && !decl->right) {
2046 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Missing initializer in const declaration");
2047 return mk(N_EMPTY);
2048 }
2049 }
2050 }
2051
2052 sv_ast_t *n = mk(N_FOR);
2053 n->init = init_node;
2054 expect(p, TOK_SEMICOLON);
2055 if (NEXT() != TOK_SEMICOLON)
2056 n->cond = parse_expr(p);
2057 expect(p, TOK_SEMICOLON);
2058 if (NEXT() != TOK_RPAREN)
2059 n->update = parse_expr(p);
2060 expect(p, TOK_RPAREN);
2061 n->body = parse_stmt(p);
2062 return n;
2063 }
2064
2065 l_return: {
2066 CONSUME();
2067 sv_ast_t *n = mk(N_RETURN);
2068 if (NEXT() != TOK_SEMICOLON && TOK != TOK_RBRACE && TOK != TOK_EOF &&
2069 !HAD_NEWLINE)
2070 n->right = parse_expr(p);
2071 if (NEXT() == TOK_SEMICOLON) CONSUME();
2072 return n;
2073 }
2074
2075 l_throw: {
2076 CONSUME();
2077 sv_ast_t *n = mk(N_THROW);
2078 n->right = parse_expr(p);
2079 if (NEXT() == TOK_SEMICOLON) CONSUME();
2080 return n;
2081 }
2082
2083 l_break: {
2084 CONSUME();
2085 sv_ast_t *n = mk(N_BREAK);
2086 if ((NEXT() == TOK_IDENTIFIER || is_contextual_ident_tok(TOK)) && !HAD_NEWLINE) {
2087 n->str = tok_ident_str(p, &n->len);
2088 CONSUME();
2089 }
2090 if (NEXT() == TOK_SEMICOLON) CONSUME();
2091 return n;
2092 }
2093
2094 l_continue: {
2095 CONSUME();
2096 sv_ast_t *n = mk(N_CONTINUE);
2097 if ((NEXT() == TOK_IDENTIFIER || is_contextual_ident_tok(TOK)) && !HAD_NEWLINE) {
2098 n->str = tok_ident_str(p, &n->len);
2099 CONSUME();
2100 }
2101 if (NEXT() == TOK_SEMICOLON) CONSUME();
2102 return n;
2103 }
2104
2105 l_try: {
2106 CONSUME();
2107 sv_ast_t *n = mk(N_TRY);
2108 n->body = parse_block(p, false);
2109 if (NEXT() == TOK_CATCH) {
2110 CONSUME();
2111 if (NEXT() == TOK_LPAREN) {
2112 CONSUME();
2113 n->catch_param = parse_binding_pattern(p);
2114 if (n->catch_param->type == N_IDENT)
2115 sv_strict_check_binding_ident(p, n->catch_param->str, n->catch_param->len);
2116 expect(p, TOK_RPAREN);
2117 }
2118 n->catch_body = parse_block(p, false);
2119 }
2120 if (NEXT() == TOK_FINALLY) {
2121 CONSUME();
2122 n->finally_body = parse_block(p, false);
2123 }
2124 return n;
2125 }
2126
2127 l_switch: {
2128 CONSUME();
2129 sv_ast_t *n = mk(N_SWITCH);
2130 expect(p, TOK_LPAREN);
2131 n->cond = parse_expr(p);
2132 expect(p, TOK_RPAREN);
2133 expect(p, TOK_LBRACE);
2134 while (NEXT() != TOK_RBRACE && TOK != TOK_EOF) {
2135 sv_ast_t *c = mk(N_CASE);
2136 if (TOK == TOK_CASE) {
2137 CONSUME();
2138 c->left = parse_expr(p);
2139 } else if (TOK == TOK_DEFAULT) {
2140 CONSUME();
2141 }
2142 expect(p, TOK_COLON);
2143 while (NEXT() != TOK_CASE && TOK != TOK_DEFAULT &&
2144 TOK != TOK_RBRACE && TOK != TOK_EOF)
2145 sv_ast_list_push(&c->args, parse_stmt(p));
2146 sv_ast_list_push(&n->args, c);
2147 }
2148 expect(p, TOK_RBRACE);
2149 return n;
2150 }
2151
2152 l_debugger: { CONSUME(); if (NEXT() == TOK_SEMICOLON) CONSUME(); return mk(N_DEBUGGER); }
2153
2154 l_with: {
2155 if (p->lx.strict) {
2156 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "with statement not allowed in strict mode");
2157 return mk(N_EMPTY);
2158 }
2159 CONSUME();
2160 sv_ast_t *n = mk(N_WITH);
2161 expect(p, TOK_LPAREN);
2162 n->left = parse_expr(p);
2163 expect(p, TOK_RPAREN);
2164 n->body = parse_stmt(p);
2165 return n;
2166 }
2167
2168 l_func: {
2169 CONSUME();
2170 return parse_func(p);
2171 }
2172
2173 l_class: {
2174 uint32_t class_off = (uint32_t)TOFF;
2175 CONSUME();
2176 sv_ast_t *cls = parse_class(p);
2177 cls->src_off = class_off;
2178 return cls;
2179 }
2180
2181 l_async: {
2182 uint8_t la = LA();
2183 uint32_t async_off = (uint32_t)TOFF;
2184 if (la == TOK_FUNC && !lookahead_crosses_line_terminator(p)) {
2185 CONSUME();
2186 NEXT(); CONSUME();
2187 sv_ast_t *fn = parse_func(p);
2188 fn->flags |= FN_ASYNC;
2189 fn->src_off = async_off;
2190 return fn;
2191 }
2192 goto l_expr_stmt;
2193 }
2194
2195 l_import: {
2196 uint8_t la = LA();
2197 if (la == TOK_LPAREN || la == TOK_DOT)
2198 goto l_expr_stmt;
2199 CONSUME();
2200 return parse_import_stmt(p);
2201 }
2202
2203 l_export: {
2204 CONSUME();
2205 return parse_export_stmt(p);
2206 }
2207
2208 l_expr_stmt: {
2209 if (TOK == TOK_IDENTIFIER || is_contextual_ident_tok(TOK)) {
2210 uint8_t la = LA();
2211 if (la == TOK_COLON) {
2212 sv_ast_t *label = mk(N_LABEL);
2213 label->str = tok_ident_str(p, &label->len);
2214 CONSUME();
2215 NEXT(); CONSUME();
2216 label->body = parse_stmt(p);
2217 return label;
2218 }
2219 }
2220
2221 sv_ast_t *expr = parse_expr(p);
2222 if (NEXT() == TOK_SEMICOLON) CONSUME();
2223 return expr;
2224 }
2225}
2226
2227sv_ast_t *sv_parse(ant_t *js, const char *code, ant_offset_t clen, bool strict){
2228 if (sv_parse_trace_unlikely) {
2229 fprintf(stderr, "[parse] start len=%u strict=%d\n", (unsigned)clen, strict ? 1 : 0);
2230 }
2231
2232 sv_parser_t parser = { .js = js };
2233 sv_parser_t *p = &parser;
2234 sv_lexer_init(&p->lx, js, code, clen, strict);
2235
2236 sv_ast_t *program = mk(N_PROGRAM);
2237 sv_parse_stmt_list(p, &program->args, false, true);
2238 if (sv_parse_trace_unlikely) fprintf(
2239 stderr, "[parse] after-stmt-list thrown=%d strict=%d body=%d\n",
2240 js->thrown_exists ? 1 : 0,
2241 p->lx.strict ? 1 : 0,
2242 program ? program->args.count : -1
2243 );
2244
2245 if (js->thrown_exists) {
2246 if (sv_parse_trace_unlikely) fprintf(stderr, "[parse] return null\n");
2247 return NULL;
2248 }
2249
2250 if (p->lx.strict) program->flags |= FN_PARSE_STRICT;
2251 if (sv_parse_trace_unlikely) fprintf(stderr,
2252 "[parse] return program strict=%d body=%d\n",
2253 p->lx.strict ? 1 : 0, program->args.count
2254 );
2255
2256 return program;
2257}