diff options
author | Himbeer <himbeer@disroot.org> | 2024-09-26 14:39:02 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-09-26 14:39:02 +0200 |
commit | b2b5f220d05e36da65517ab0e4969798b911b916 (patch) | |
tree | 5b45c2cafd752a52b6a0a38187f3dcb97672f806 | |
parent | 8ea5034f93cc0d06cdad8bcefc02a57d9e562146 (diff) |
Implement literal (expression) parsing
-rw-r--r-- | include/expr.h | 8 | ||||
-rw-r--r-- | src/parse.c | 107 |
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; |