From 5767110816ca9452ef77d15245d1a747bfdd896b Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 30 Aug 2026 03:32:51 +0200 Subject: add: top level parser --- src/parser/parser.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/parser/parser.c (limited to 'src/parser/parser.c') 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 + +#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; +} -- cgit v1.3