aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-09-26 14:39:02 +0200
committerHimbeer <himbeer@disroot.org>2024-09-26 14:39:02 +0200
commitb2b5f220d05e36da65517ab0e4969798b911b916 (patch)
tree5b45c2cafd752a52b6a0a38187f3dcb97672f806
parent8ea5034f93cc0d06cdad8bcefc02a57d9e562146 (diff)
Implement literal (expression) parsing
-rw-r--r--include/expr.h8
-rw-r--r--src/parse.c107
2 files changed, 106 insertions, 9 deletions
diff --git a/include/expr.h b/include/expr.h
index 5b0ce59..5a16f30 100644
--- a/include/expr.h
+++ b/include/expr.h
@@ -6,11 +6,11 @@
struct number_e {
struct number value;
- struct type type;
+ struct type *type;
};
struct array_e {
- struct cer_array meta;
+ struct cer_array *meta;
struct disjunction_e *elems;
int elemsz, elemlen;
};
@@ -33,7 +33,7 @@ struct literal_e {
};
struct call_e {
- struct path path;
+ struct path *path;
struct disjunction_e *args;
int argsz, arglen;
};
@@ -51,7 +51,7 @@ struct primary_e {
struct disjunction_e *grp;
struct literal_e lit;
struct call_e call;
- struct path path;
+ struct path *path;
} prim;
};
diff --git a/src/parse.c b/src/parse.c
index b235b24..1e9a593 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -9,6 +9,7 @@
static bool parse_disjunction_e(struct lexer *lexer,
struct disjunction_e *out);
+static bool parse_array(struct lexer *lexer, struct type *out);
static bool parse_type(struct lexer *lexer, struct type *out);
static noreturn void
@@ -81,10 +82,103 @@ parse_grouping_e(struct lexer *lexer, struct disjunction_e *out)
}
static bool
+parse_bool_lit(struct lexer *lexer, bool *out)
+{
+ if (match(lexer, T_TRUE)) {
+ *out = true;
+ } else if (match(lexer, T_FALSE)) {
+ *out = false;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+parse_string(struct lexer *lexer, char **out)
+{
+ *out = NULL;
+
+ struct token s;
+ while (lex(lexer, &s) == T_STRING) {
+ if (*out) {
+ *out = strdup(s.info.str);
+ } else {
+ size_t sz = strlen(*out) + strlen(s.info.str) + 1;
+ *out = must_realloc(*out, sz);
+ }
+ }
+ unlex(lexer, &s);
+
+ return true;
+}
+
+static bool
+parse_number_e(struct lexer *lexer, struct number_e *out)
+{
+ struct token num;
+ if (lex(lexer, &num) != T_NUMBER) {
+ return false;
+ }
+ out->value = num.info.num;
+
+ out->type = must_malloc(sizeof(struct type));
+ if (!parse_type(lexer, out->type)) {
+ error(lex_loc(lexer), "syntax error: expected type");
+ }
+
+ return true;
+}
+
+static bool
+parse_array_e(struct lexer *lexer, struct array_e *out)
+{
+ struct type type;
+ if (!parse_array(lexer, &type)) {
+ return false;
+ }
+ out->meta = must_malloc(sizeof(struct cer_array));
+ *out->meta = type.desc.array;
+
+ out->elems = must_calloc(1, sizeof(struct disjunction_e));
+ out->elemsz = 1;
+ out->elemlen = 0;
+
+ struct disjunction_e elem;
+ while (parse_disjunction_e(lexer, &elem)) {
+ if (out->elemlen >= out->elemsz) {
+ out->elemsz *= 2;
+ size_t sz = sizeof(struct disjunction_e) * out->elemsz;
+ out->elems = must_realloc(out->elems, sz);
+ }
+ out->elems[out->elemlen++] = elem;
+ }
+
+ return true;
+}
+
+static bool
parse_literal_e(struct lexer *lexer, struct literal_e *out)
{
- /* TODO */
- error(lex_loc(lexer), "unimplemented: literals");
+ if (parse_bool_lit(lexer, &out->lit.b)) {
+ out->kind = LIT_BOOL;
+ return true;
+ }
+ if (parse_string(lexer, &out->lit.str)) {
+ out->kind = LIT_STRING;
+ return true;
+ }
+ if (parse_number_e(lexer, &out->lit.num)) {
+ out->kind = LIT_NUMBER;
+ return true;
+ }
+ if (parse_array_e(lexer, &out->lit.arr)) {
+ out->kind = LIT_ARRAY;
+ return true;
+ }
+
+ return false;
}
// Invariant: Only called from parse_primary_e with path already consumed.
@@ -95,7 +189,9 @@ parse_call_e(struct lexer *lexer, struct call_e *out, struct path path)
return false;
}
- out->path = path;
+ out->path = must_malloc(sizeof(struct path));
+ *out->path = path;
+
out->args = must_calloc(1, sizeof(struct disjunction_e));
out->argsz = 1;
out->arglen = 0;
@@ -130,9 +226,10 @@ parse_primary_e(struct lexer *lexer, struct primary_e *out)
out->kind = PRM_LITERAL;
return true;
}
- if (parse_path(lexer, &out->prim.path)) {
+ out->prim.path = must_malloc(sizeof(struct path));
+ if (parse_path(lexer, out->prim.path)) {
out->kind = PRM_PATH;
- if (parse_call_e(lexer, &out->prim.call, out->prim.path)) {
+ if (parse_call_e(lexer, &out->prim.call, *out->prim.path)) {
out->kind = PRM_CALL;
}
return true;