summaryrefslogtreecommitdiff
path: root/uscript/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'uscript/parser.c')
-rw-r--r--uscript/parser.c86
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);