diff options
| author | hachem <im@hachem.wtf> | 2026-08-30 03:32:51 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-30 03:32:51 +0200 |
| commit | 5767110816ca9452ef77d15245d1a747bfdd896b (patch) | |
| tree | 1f7e5dec5f1fb4fe7a53c1c81f94043ba7db5676 /src/parser | |
| parent | 6a6e79cb233e795b78c9ec750dbae9d26bd51654 (diff) | |
add: top level parser
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/ast.c | 33 | ||||
| -rw-r--r-- | src/parser/ast.h | 22 | ||||
| -rw-r--r-- | src/parser/parser.c | 86 | ||||
| -rw-r--r-- | src/parser/parser.h | 8 |
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); |
