diff options
Diffstat (limited to 'uscript/parser.c')
| -rw-r--r-- | uscript/parser.c | 86 |
1 files changed, 77 insertions, 9 deletions
diff --git a/uscript/parser.c b/uscript/parser.c index f90e6d0..2bb1afa 100644 --- a/uscript/parser.c +++ b/uscript/parser.c @@ -401,6 +401,58 @@ void parse_arr(struct parser *p) } static +void parse_map_literal_entry(struct parser *p) +{ + + if (consume(p, '[')) { + expr(p); + expect(p, ']', "unterminated key"); + } else { + expect( + p, + TOKEN_IDENT, + "expected property name" + ); + parser_add_const( + p, + wrap_str(copy_str(p->prev.start, p->prev.len)) + ); + } + + expect(p, '=', "expected '='"); + + expr(p); +} + +static +void parse_map(struct parser *p) +{ + int map_len = 0; + + if (p->cur.kind != '}') { + do { + if (p->cur.kind == '}') + break; + if (map_len > UINT8_MAX) { + show_error( + p, + p->prev, + "too many elements in map literal " + "(%d/%d)", + map_len, UINT8_MAX + ); + } + parse_map_literal_entry(p); + map_len++; + } while (consume(p, ',')); + } + expect(p, '}', "unterminated map literal"); + + parser_add_byte(p, BC_MAP); + parser_add_byte(p, map_len); +} + +static void parser_add_var_access(struct parser *p, u8 acc, int var) { parser_add_byte(p, acc); @@ -547,13 +599,8 @@ void parse_call(struct parser *p) } static -void parse_index(struct parser *p) +void index_access(struct parser *p, bool can_assign) { - bool can_assign = p->can_assign; - - expr(p); - expect(p, ']', "expected ']'"); - #define compound_op(op) \ do { \ parser_add_byte(p, BC_PUSH_INDEX); \ @@ -582,17 +629,38 @@ void parse_index(struct parser *p) } static +void parse_index(struct parser *p) +{ + bool can_assign = p->can_assign; + expr(p); + expect(p, ']', "expected ']'"); + + index_access(p, can_assign); +} + +static +void parse_dot(struct parser *p) +{ + bool can_assign = p->can_assign; + expect(p, TOKEN_IDENT, "expected property name"); + parser_add_const(p, wrap_str(copy_str(p->prev.start, p->prev.len))); + + index_access(p, can_assign); +} +#undef compound_op + +static struct expr expressions[] = { ['('] = {parse_grouping, parse_call, PREC_CALL}, [')'] = {NULL, NULL, PREC_NONE}, - ['{'] = {NULL, NULL, PREC_NONE}, + ['{'] = {parse_map, NULL, PREC_NONE}, ['}'] = {NULL, NULL, PREC_NONE}, ['['] = {parse_arr, parse_index, PREC_CALL}, [']'] = {NULL, NULL, PREC_NONE}, [','] = {NULL, NULL, PREC_NONE}, [';'] = {NULL, NULL, PREC_NONE}, [':'] = {NULL, NULL, PREC_NONE}, - ['.'] = {NULL, NULL, PREC_NONE}, + ['.'] = {NULL, parse_dot, PREC_CALL}, ['+'] = {NULL, parse_binary, PREC_TERM}, ['-'] = {parse_unary, parse_binary, PREC_TERM}, ['*'] = {NULL, parse_binary, PREC_FACTOR}, @@ -745,7 +813,7 @@ void fun_stat(struct parser *p, bool is_global) } else { while (p->cur.kind != TOKEN_END && p->cur.kind != TOKEN_EOF) stat(p); - expect(p, TOKEN_END, "unterminated function"); + expect(p, TOKEN_END, "unterminated function"); } end_function(p); |
