aboutsummaryrefslogtreecommitdiff
path: root/src/parse.c
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-10-07 13:32:07 +0200
committerHimbeer <himbeer@disroot.org>2024-10-07 13:32:07 +0200
commit991d4095ba596c55ef4d043a496d5cf63fd667d1 (patch)
tree81b8cbb600c8c57c00b7df01fa9cea5563de23ee /src/parse.c
parent5ba544c4e016de3d61a296ceeaf7c4a143f3c118 (diff)
Implement expression-based language redesign
This is the implementation of commit ce68792c848caee2f184e7a6392d9f1e958da1a1.
Diffstat (limited to 'src/parse.c')
-rw-r--r--src/parse.c94
1 files changed, 53 insertions, 41 deletions
diff --git a/src/parse.c b/src/parse.c
index ee115d8..c5ced09 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -12,6 +12,9 @@ static bool parse_disjunction_e(struct lexer *lexer,
static bool parse_array(struct lexer *lexer, struct type *out);
static bool parse_type(struct lexer *lexer, struct type *out);
static bool parse_block(struct lexer *lexer, struct ast_block *out);
+static bool parse_control_e(struct lexer *lexer, struct control_e *out);
+static bool parse_location(struct lexer *lexer, struct location_e *out);
+static bool parse_assignment_e(struct lexer *lexer, struct assign_e *out);
static noreturn void
error(struct location loc, const char *fmt, ...)
@@ -188,14 +191,13 @@ parse_literal_e(struct lexer *lexer, struct literal_e *out)
// Invariant: Only called from parse_primary_e with path already consumed.
static bool
-parse_call_e(struct lexer *lexer, struct call_e *out, struct path path)
+parse_call_e(struct lexer *lexer, struct call_e *out, struct location_e *loc)
{
if (!match(lexer, T_LPAREN)) {
return false;
}
- out->path = must_malloc(sizeof(struct path));
- *out->path = path;
+ out->loc = loc;
out->args = must_calloc(1, sizeof(struct disjunction_e));
out->argsz = 1;
@@ -219,8 +221,32 @@ parse_call_e(struct lexer *lexer, struct call_e *out, struct path path)
}
static bool
+parse_named_e(struct lexer *lexer, struct named_e *out)
+{
+ if (!parse_location(lexer, &out->loc)) {
+ return false;
+ }
+
+ if (parse_assignment_e(lexer, &out->nmd.assign)) {
+ out->kind = NMD_ASSIGN;
+ return true;
+ }
+ if (parse_call_e(lexer, &out->nmd.call, &out->loc)) {
+ out->kind = NMD_CALL;
+ return true;
+ }
+
+ out->kind = NMD_LOCATION;
+ return true;
+}
+
+static bool
parse_primary_e(struct lexer *lexer, struct primary_e *out)
{
+ if (parse_control_e(lexer, &out->prim.ctl)) {
+ out->kind = PRM_CONTROL;
+ return true;
+ }
out->prim.grp = must_malloc(sizeof(struct disjunction_e));
if (parse_grouping_e(lexer, out->prim.grp)) {
out->kind = PRM_GROUPING;
@@ -231,14 +257,12 @@ parse_primary_e(struct lexer *lexer, struct primary_e *out)
out->kind = PRM_LITERAL;
return true;
}
- 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)) {
- out->kind = PRM_CALL;
- }
+ if (parse_named_e(lexer, &out->prim.nmd)) {
+ out->kind = PRM_NAMED;
return true;
}
+
+ return false;
}
static bool
@@ -1178,7 +1202,8 @@ parse_declaration(struct lexer *lexer, struct ast_declaration *out)
error(lex_loc(lexer), "syntax error: expected '='");
}
- if (!parse_expr(lexer, &out->value)) {
+ out->value = must_malloc(sizeof(struct ast_expr));
+ if (!parse_expr(lexer, out->value)) {
error(lex_loc(lexer), "syntax error: expected expression");
}
@@ -1235,11 +1260,11 @@ parse_loc_postfix(struct lexer *lexer, struct loc_postfix *out)
}
static bool
-parse_location(struct lexer *lexer, struct ast_location *out)
+parse_location(struct lexer *lexer, struct location_e *out)
{
- struct token name;
- if (lex(lexer, &name) != T_NAME) {
- unlex(lexer, &name);
+ out->path = must_malloc(sizeof(struct path));
+ if (!parse_path(lexer, out->path)) {
+ free(out->path);
return false;
}
@@ -1261,7 +1286,7 @@ parse_location(struct lexer *lexer, struct ast_location *out)
}
static bool
-parse_assignment(struct lexer *lexer, struct ast_assign *out)
+parse_assignment_e(struct lexer *lexer, struct assign_e *out)
{
if (!parse_location(lexer, &out->dst)) {
return false;
@@ -1271,7 +1296,8 @@ parse_assignment(struct lexer *lexer, struct ast_assign *out)
error(lex_loc(lexer), "syntax error: expected '='");
}
- if (!parse_expr(lexer, &out->value)) {
+ out->value = must_malloc(sizeof(struct ast_expr));
+ if (!parse_expr(lexer, out->value)) {
error(lex_loc(lexer), "syntax error: expected expression");
}
@@ -1292,12 +1318,12 @@ parse_defer(struct lexer *lexer, struct call_e *out)
return false;
}
- struct path path;
- if (!parse_path(lexer, &path)) {
+ struct location_e *loc = must_malloc(sizeof(struct location_e));
+ if (!parse_location(lexer, loc)) {
error(lex_loc(lexer), "syntax error: expected path");
}
- if (!parse_call_e(lexer, out, path)) {
+ if (!parse_call_e(lexer, out, loc)) {
error(lex_loc(lexer), "syntax error: expected call");
}
@@ -1335,33 +1361,21 @@ parse_statement(struct lexer *lexer, struct ast_statement *out)
}
return true;
}
- if (parse_assignment(lexer, &out->stmt.assign)) {
- out->action = STM_ASSIGN;
- if (!match(lexer, T_SEMICOLON)) {
- error(lex_loc(lexer), "syntax error: expected semicolon");
- }
- return true;
- }
- if (parse_call(lexer, &out->stmt.call)) {
- out->action = STM_CALL;
- if (!match(lexer, T_SEMICOLON)) {
- error(lex_loc(lexer), "syntax error: expected semicolon");
- }
- return true;
- }
- if (parse_defer(lexer, &out->stmt.call)) {
+ out->stmt.call = must_malloc(sizeof(struct call_e));
+ if (parse_defer(lexer, out->stmt.call)) {
out->action = STM_DEFER;
if (!match(lexer, T_SEMICOLON)) {
error(lex_loc(lexer), "syntax error: expected semicolon");
}
return true;
}
+ free(out->stmt.call);
return false;
}
static bool
-parse_control(struct lexer *lexer, struct ast_control *out)
+parse_control_e(struct lexer *lexer, struct control_e *out)
{
/* TODO */
return false;
@@ -1378,10 +1392,6 @@ parse_command(struct lexer *lexer, struct ast_cmd *out)
out->kind = CMD_STATEMENT;
return true;
}
- if (parse_control(lexer, &out->cmd.ctl)) {
- out->kind = CMD_CONTROL;
- return true;
- }
return false;
}
@@ -1476,9 +1486,11 @@ parse_function(struct lexer *lexer, struct ast_func *out)
error(lex_loc(lexer), "syntax error: expected ')'");
}
- bool nonvoid = parse_type(lexer, &out->ret);
+ out->ret = must_malloc(sizeof(struct type));
+ bool nonvoid = parse_type(lexer, out->ret);
- if (!parse_block(lexer, &out->block)) {
+ out->block = must_malloc(sizeof(struct ast_block));
+ if (!parse_block(lexer, out->block)) {
error(lex_loc(lexer), "syntax error: expected block");
}