aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-30 03:32:51 +0200
committerhachem <im@hachem.wtf>2026-08-30 03:32:51 +0200
commit5767110816ca9452ef77d15245d1a747bfdd896b (patch)
tree1f7e5dec5f1fb4fe7a53c1c81f94043ba7db5676 /src/parser
parent6a6e79cb233e795b78c9ec750dbae9d26bd51654 (diff)
add: top level parser
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c33
-rw-r--r--src/parser/ast.h22
-rw-r--r--src/parser/parser.c86
-rw-r--r--src/parser/parser.h8
4 files changed, 149 insertions, 0 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
new file mode 100644
index 0000000..979dff0
--- /dev/null
+++ b/src/parser/ast.c
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+
+#include "parser/ast.h"
+
+struct Program create_program(void)
+{
+ struct Program program;
+ program.consts = NULL;
+ program.const_count = 0;
+ program.const_capacity = 0;
+ return program;
+}
+
+void free_program(struct Program* program)
+{
+ free(program->consts);
+ program->consts = NULL;
+ program->const_count = 0;
+ program->const_capacity = 0;
+}
+
+void add_const(struct Program* program, struct ConstDecl decl)
+{
+ if (program->const_count == program->const_capacity)
+ {
+ size_t capacity = program->const_capacity < 8 ? 8 : program->const_capacity * 2;
+ program->consts = realloc(program->consts, capacity * sizeof(struct ConstDecl));
+ program->const_capacity = capacity;
+ }
+
+ program->consts[program->const_count] = decl;
+ program->const_count += 1;
+}
diff --git a/src/parser/ast.h b/src/parser/ast.h
new file mode 100644
index 0000000..7079305
--- /dev/null
+++ b/src/parser/ast.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <stddef.h>
+
+#include "lexer/lexer.h"
+
+struct ConstDecl
+{
+ struct Token name;
+ struct Token value;
+};
+
+struct Program
+{
+ struct ConstDecl* consts;
+ size_t const_count;
+ size_t const_capacity;
+};
+
+struct Program create_program(void);
+void free_program(struct Program* program);
+void add_const(struct Program* program, struct ConstDecl decl);
diff --git a/src/parser/parser.c b/src/parser/parser.c
new file mode 100644
index 0000000..5845ad4
--- /dev/null
+++ b/src/parser/parser.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+
+#include "parser/parser.h"
+
+struct Parser
+{
+ struct Lexer* lexer;
+ struct Token current;
+ struct Token previous;
+ bool had_error;
+};
+
+static void advance_parser(struct Parser* parser)
+{
+ parser->previous = parser->current;
+ parser->current = scan_token(parser->lexer);
+}
+
+static bool check(struct Parser* parser, enum TokenType type)
+{
+ return parser->current.type == type;
+}
+
+static void error_at(struct Parser* parser, struct Token token, const char* message)
+{
+ fprintf(stderr, "error: line %u: %s\n", token.line, message);
+ parser->had_error = true;
+}
+
+static bool consume(struct Parser* parser, enum TokenType type, const char* message)
+{
+ if (check(parser, type))
+ {
+ advance_parser(parser);
+ return true;
+ }
+
+ error_at(parser, parser->current, message);
+ return false;
+}
+
+static bool parse_const(struct Parser* parser, struct Program* program)
+{
+ struct ConstDecl decl;
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected constant name after 'const'"))
+ return false;
+ decl.name = parser->previous;
+
+ if (!consume(parser, TOKEN_EQUAL, "expected '=' after constant name"))
+ return false;
+
+ if (!consume(parser, TOKEN_INTEGER, "expected integer value after '='"))
+ return false;
+ decl.value = parser->previous;
+
+ add_const(program, decl);
+ return true;
+}
+
+bool parse_program(struct Lexer* lexer, struct Program* out)
+{
+ struct Parser parser;
+ parser.lexer = lexer;
+ parser.had_error = false;
+ advance_parser(&parser);
+
+ *out = create_program();
+
+ while (!check(&parser, TOKEN_EOF))
+ {
+ if (check(&parser, TOKEN_CONST))
+ {
+ advance_parser(&parser);
+ if (!parse_const(&parser, out))
+ return false;
+ }
+ else
+ {
+ error_at(&parser, parser.current, "expected a top-level declaration");
+ return false;
+ }
+ }
+
+ return !parser.had_error;
+}
diff --git a/src/parser/parser.h b/src/parser/parser.h
new file mode 100644
index 0000000..82d306a
--- /dev/null
+++ b/src/parser/parser.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <stdbool.h>
+
+#include "lexer/lexer.h"
+#include "parser/ast.h"
+
+bool parse_program(struct Lexer* lexer, struct Program* out);