From 4ffc0c48d0823bcc48bf88aed67324b6266810c5 Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 30 Aug 2026 04:59:36 +0200 Subject: add: parse assignment statements into procedures --- src/main.c | 14 +++++++++++ src/parser/ast.c | 19 +++++++++++++++ src/parser/ast.h | 28 ++++++++++++++++++++++ src/parser/parser.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 120 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index e65362c..2f5f4d1 100644 --- a/src/main.c +++ b/src/main.c @@ -58,6 +58,20 @@ int main(int argc, char** argv) (int)param.reg.length, param.reg.start); } printf(")\n"); + + for (size_t s = 0; s < proc.body_count; s += 1) + { + struct Statement statement = proc.body[s]; + if (statement.kind == STATEMENT_ASSIGN) + { + struct AssignStatement assign = statement.assign; + printf(" %s%.*s %.*s %.*s\n", + assign.target_deref ? "^" : "", + (int)assign.target.length, assign.target.start, + (int)assign.op.length, assign.op.start, + (int)assign.value.length, assign.value.start); + } + } } free_program(&program); diff --git a/src/parser/ast.c b/src/parser/ast.c index b002ff2..4f10915 100644 --- a/src/parser/ast.c +++ b/src/parser/ast.c @@ -23,7 +23,10 @@ void free_program(struct Program* program) free(program->data_decls); for (size_t i = 0; i < program->proc_count; i += 1) + { free(program->procs[i].params); + free(program->procs[i].body); + } free(program->procs); program->consts = NULL; @@ -70,6 +73,9 @@ struct ProcDecl create_proc(void) proc.params = NULL; proc.param_count = 0; proc.param_capacity = 0; + proc.body = NULL; + proc.body_count = 0; + proc.body_capacity = 0; return proc; } @@ -86,6 +92,19 @@ void add_param(struct ProcDecl* proc, struct Param param) proc->param_count += 1; } +void add_statement(struct ProcDecl* proc, struct Statement statement) +{ + if (proc->body_count == proc->body_capacity) + { + size_t capacity = proc->body_capacity < 8 ? 8 : proc->body_capacity * 2; + proc->body = realloc(proc->body, capacity * sizeof(struct Statement)); + proc->body_capacity = capacity; + } + + proc->body[proc->body_count] = statement; + proc->body_count += 1; +} + void add_proc(struct Program* program, struct ProcDecl decl) { if (program->proc_count == program->proc_capacity) diff --git a/src/parser/ast.h b/src/parser/ast.h index 665bfd2..83483e9 100644 --- a/src/parser/ast.h +++ b/src/parser/ast.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "lexer/lexer.h" @@ -22,12 +23,38 @@ struct Param struct Token reg; }; +enum StatementKind +{ + STATEMENT_ASSIGN, +}; + +struct AssignStatement +{ + bool target_deref; + struct Token target; + struct Token op; + struct Token value; +}; + +struct Statement +{ + enum StatementKind kind; + union + { + struct AssignStatement assign; + }; +}; + struct ProcDecl { struct Token name; struct Param* params; size_t param_count; size_t param_capacity; + + struct Statement* body; + size_t body_count; + size_t body_capacity; }; struct Program @@ -52,4 +79,5 @@ void add_data(struct Program* program, struct DataDecl decl); struct ProcDecl create_proc(void); void add_param(struct ProcDecl* proc, struct Param param); +void add_statement(struct ProcDecl* proc, struct Statement statement); void add_proc(struct Program* program, struct ProcDecl decl); diff --git a/src/parser/parser.c b/src/parser/parser.c index acd4b7a..d86502f 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -114,6 +114,56 @@ static bool parse_params(struct Parser* parser, struct ProcDecl* proc) return true; } +static bool is_assign_op(enum TokenType type) +{ + return type == TOKEN_EQUAL + || type == TOKEN_PLUS_EQUAL + || type == TOKEN_MINUS_EQUAL + || type == TOKEN_STAR_EQUAL + || type == TOKEN_SLASH_EQUAL; +} + +static bool parse_value(struct Parser* parser, struct Token* out) +{ + if (check(parser, TOKEN_IDENTIFIER) || check(parser, TOKEN_INTEGER) || check(parser, TOKEN_CHAR)) + { + advance_parser(parser); + *out = parser->previous; + return true; + } + + error_at(parser, parser->current, "expected a value"); + return false; +} + +static bool parse_statement(struct Parser* parser, struct Statement* out) +{ + bool deref = match_token(parser, TOKEN_CARET); + + if (!consume(parser, TOKEN_IDENTIFIER, "expected a statement")) + return false; + struct Token target = parser->previous; + + if (!is_assign_op(parser->current.type)) + { + error_at(parser, parser->current, "expected an assignment operator"); + return false; + } + + struct AssignStatement assign; + assign.target_deref = deref; + assign.target = target; + advance_parser(parser); + assign.op = parser->previous; + + if (!parse_value(parser, &assign.value)) + return false; + + out->kind = STATEMENT_ASSIGN; + out->assign = assign; + return true; +} + static bool parse_proc(struct Parser* parser, struct Program* program) { struct ProcDecl decl = create_proc(); @@ -133,27 +183,28 @@ static bool parse_proc(struct Parser* parser, struct Program* program) if (!consume(parser, TOKEN_LEFT_BRACE, "expected '{' to begin procedure body")) goto error; - // TODO: parse body statements; for now skip the braced block - int depth = 1; - while (depth > 0) + while (!check(parser, TOKEN_RIGHT_BRACE)) { if (check(parser, TOKEN_EOF)) { error_at(parser, parser->current, "unterminated procedure body"); goto error; } - if (check(parser, TOKEN_LEFT_BRACE)) - depth += 1; - else if (check(parser, TOKEN_RIGHT_BRACE)) - depth -= 1; - advance_parser(parser); + + struct Statement statement; + if (!parse_statement(parser, &statement)) + goto error; + + add_statement(&decl, statement); } + advance_parser(parser); add_proc(program, decl); return true; error: free(decl.params); + free(decl.body); return false; } -- cgit v1.3