aboutsummaryrefslogtreecommitdiff
path: root/src/parser/parser.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-30 04:11:27 +0200
committerhachem <im@hachem.wtf>2026-08-30 04:11:27 +0200
commitaffa20ab497911353babc9ed6c580c8a12b2bf15 (patch)
tree6d7c8d2164cbf1403819991baf62d8201049b778 /src/parser/parser.c
parent2e7cab34d22a0174909030942671e95d5a3c769f (diff)
add: parse proc declarations
Diffstat (limited to 'src/parser/parser.c')
-rw-r--r--src/parser/parser.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/parser/parser.c b/src/parser/parser.c
index 4fb85ef..acd4b7a 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <stdlib.h>
#include "parser/parser.h"
@@ -27,6 +28,15 @@ static void error_at(struct Parser* parser, struct Token token, const char* mess
parser->had_error = true;
}
+static bool match_token(struct Parser* parser, enum TokenType type)
+{
+ if (!check(parser, type))
+ return false;
+
+ advance_parser(parser);
+ return true;
+}
+
static bool consume(struct Parser* parser, enum TokenType type, const char* message)
{
if (check(parser, type))
@@ -77,6 +87,76 @@ static bool parse_data(struct Parser* parser, struct Program* program)
return true;
}
+static bool parse_params(struct Parser* parser, struct ProcDecl* proc)
+{
+ if (check(parser, TOKEN_RIGHT_PAREN))
+ return true;
+
+ do
+ {
+ struct Param param;
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected parameter name"))
+ return false;
+ param.name = parser->previous;
+
+ if (!consume(parser, TOKEN_COLON, "expected ':' after parameter name"))
+ return false;
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected register after ':'"))
+ return false;
+ param.reg = parser->previous;
+
+ add_param(proc, param);
+ }
+ while (match_token(parser, TOKEN_COMMA));
+
+ return true;
+}
+
+static bool parse_proc(struct Parser* parser, struct Program* program)
+{
+ struct ProcDecl decl = create_proc();
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected procedure name after 'proc'"))
+ goto error;
+ decl.name = parser->previous;
+
+ if (match_token(parser, TOKEN_LEFT_PAREN))
+ {
+ if (!parse_params(parser, &decl))
+ goto error;
+ if (!consume(parser, TOKEN_RIGHT_PAREN, "expected ')' after parameters"))
+ goto error;
+ }
+
+ 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)
+ {
+ 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);
+ }
+
+ add_proc(program, decl);
+ return true;
+
+error:
+ free(decl.params);
+ return false;
+}
+
bool parse_program(struct Lexer* lexer, struct Program* out)
{
struct Parser parser;
@@ -100,6 +180,12 @@ bool parse_program(struct Lexer* lexer, struct Program* out)
if (!parse_data(&parser, out))
return false;
}
+ else if (check(&parser, TOKEN_PROC))
+ {
+ advance_parser(&parser);
+ if (!parse_proc(&parser, out))
+ return false;
+ }
else
{
error_at(&parser, parser.current, "expected a top-level declaration");