aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c265
-rw-r--r--src/parser/ast.h245
-rw-r--r--src/parser/parser.c787
-rw-r--r--src/parser/parser.h8
4 files changed, 0 insertions, 1305 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
deleted file mode 100644
index 63d8a08..0000000
--- a/src/parser/ast.c
+++ /dev/null
@@ -1,265 +0,0 @@
-#include <stdlib.h>
-
-#include "parser/ast.h"
-
-void free_expr(struct Expr* expr)
-{
- if (expr == NULL)
- return;
-
- switch (expr->kind)
- {
- case EXPR_PRIMARY:
- break;
- case EXPR_UNARY:
- free_expr(expr->unary.operand);
- break;
- case EXPR_BINARY:
- free_expr(expr->binary.left);
- free_expr(expr->binary.right);
- break;
- case EXPR_MEMBER:
- free_expr(expr->member.object);
- break;
- case EXPR_DEREF:
- free_expr(expr->deref.address);
- break;
- }
-
- free(expr);
-}
-
-void free_statement(struct Statement* statement)
-{
- switch (statement->kind)
- {
- case STATEMENT_ASSIGN:
- free_expr(statement->assign.value);
- break;
- case STATEMENT_IF:
- free_expr(statement->branch.left);
- free_expr(statement->branch.right);
- for (size_t i = 0; i < statement->branch.body_count; i += 1)
- free_statement(&statement->branch.body[i]);
- free(statement->branch.body);
- for (size_t i = 0; i < statement->branch.else_count; i += 1)
- free_statement(&statement->branch.else_body[i]);
- free(statement->branch.else_body);
- break;
- case STATEMENT_CALL:
- for (size_t i = 0; i < statement->call.arg_count; i += 1)
- free_expr(statement->call.args[i]);
- free(statement->call.args);
- break;
- case STATEMENT_STACK:
- free_expr(statement->stack.size);
- break;
- default:
- break;
- }
-}
-
-void free_proc(struct ProcDecl* proc)
-{
- free(proc->params);
-
- for (size_t i = 0; i < proc->body_count; i += 1)
- free_statement(&proc->body[i]);
- free(proc->body);
-}
-
-struct Program create_program(void)
-{
- struct Program program;
- program.config.bits = 64;
- program.config.has_entry = false;
- program.config.logical_registers = false;
- program.consts = NULL;
- program.const_count = 0;
- program.const_capacity = 0;
- program.data_decls = NULL;
- program.data_count = 0;
- program.data_capacity = 0;
- program.enums = NULL;
- program.enum_count = 0;
- program.enum_capacity = 0;
- program.structs = NULL;
- program.struct_count = 0;
- program.struct_capacity = 0;
- program.procs = NULL;
- program.proc_count = 0;
- program.proc_capacity = 0;
- return program;
-}
-
-void free_program(struct Program* program)
-{
- for (size_t i = 0; i < program->const_count; i += 1)
- free_expr(program->consts[i].value);
- free(program->consts);
- free(program->data_decls);
-
- for (size_t i = 0; i < program->enum_count; i += 1)
- free(program->enums[i].members);
- free(program->enums);
-
- for (size_t i = 0; i < program->struct_count; i += 1)
- free(program->structs[i].fields);
- free(program->structs);
-
- for (size_t i = 0; i < program->proc_count; i += 1)
- free_proc(&program->procs[i]);
- free(program->procs);
-
- program->consts = NULL;
- program->const_count = 0;
- program->const_capacity = 0;
- program->data_decls = NULL;
- program->data_count = 0;
- program->data_capacity = 0;
- program->enums = NULL;
- program->enum_count = 0;
- program->enum_capacity = 0;
- program->structs = NULL;
- program->struct_count = 0;
- program->struct_capacity = 0;
- program->procs = NULL;
- program->proc_count = 0;
- program->proc_capacity = 0;
-}
-
-// TODO: generalize this growable-array boilerplate once a third list appears
-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;
-}
-
-void add_data(struct Program* program, struct DataDecl decl)
-{
- if (program->data_count == program->data_capacity)
- {
- size_t capacity = program->data_capacity < 8 ? 8 : program->data_capacity * 2;
- program->data_decls = realloc(program->data_decls, capacity * sizeof(struct DataDecl));
- program->data_capacity = capacity;
- }
-
- program->data_decls[program->data_count] = decl;
- program->data_count += 1;
-}
-
-struct EnumDecl create_enum(void)
-{
- struct EnumDecl decl = { 0 };
- return decl;
-}
-
-void add_enum_member(struct EnumDecl* decl, struct Token member)
-{
- if (decl->member_count == decl->member_capacity)
- {
- size_t capacity = decl->member_capacity < 8 ? 8 : decl->member_capacity * 2;
- decl->members = realloc(decl->members, capacity * sizeof(struct Token));
- decl->member_capacity = capacity;
- }
-
- decl->members[decl->member_count] = member;
- decl->member_count += 1;
-}
-
-void add_enum(struct Program* program, struct EnumDecl decl)
-{
- if (program->enum_count == program->enum_capacity)
- {
- size_t capacity = program->enum_capacity < 8 ? 8 : program->enum_capacity * 2;
- program->enums = realloc(program->enums, capacity * sizeof(struct EnumDecl));
- program->enum_capacity = capacity;
- }
-
- program->enums[program->enum_count] = decl;
- program->enum_count += 1;
-}
-
-struct StructDecl create_struct(void)
-{
- struct StructDecl decl = { 0 };
- return decl;
-}
-
-void add_struct_field(struct StructDecl* decl, struct StructField field)
-{
- if (decl->field_count == decl->field_capacity)
- {
- size_t capacity = decl->field_capacity < 8 ? 8 : decl->field_capacity * 2;
- decl->fields = realloc(decl->fields, capacity * sizeof(struct StructField));
- decl->field_capacity = capacity;
- }
-
- decl->fields[decl->field_count] = field;
- decl->field_count += 1;
-}
-
-void add_struct(struct Program* program, struct StructDecl decl)
-{
- if (program->struct_count == program->struct_capacity)
- {
- size_t capacity = program->struct_capacity < 8 ? 8 : program->struct_capacity * 2;
- program->structs = realloc(program->structs, capacity * sizeof(struct StructDecl));
- program->struct_capacity = capacity;
- }
-
- program->structs[program->struct_count] = decl;
- program->struct_count += 1;
-}
-
-struct ProcDecl create_proc(void)
-{
- struct ProcDecl proc = { 0 };
- return proc;
-}
-
-void add_param(struct ProcDecl* proc, struct Param param)
-{
- if (proc->param_count == proc->param_capacity)
- {
- size_t capacity = proc->param_capacity < 4 ? 4 : proc->param_capacity * 2;
- proc->params = realloc(proc->params, capacity * sizeof(struct Param));
- proc->param_capacity = capacity;
- }
-
- proc->params[proc->param_count] = 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)
- {
- size_t capacity = program->proc_capacity < 8 ? 8 : program->proc_capacity * 2;
- program->procs = realloc(program->procs, capacity * sizeof(struct ProcDecl));
- program->proc_capacity = capacity;
- }
-
- program->procs[program->proc_count] = decl;
- program->proc_count += 1;
-}
diff --git a/src/parser/ast.h b/src/parser/ast.h
deleted file mode 100644
index 288bddf..0000000
--- a/src/parser/ast.h
+++ /dev/null
@@ -1,245 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "lexer/lexer.h"
-
-enum StoreSize
-{
- STORE_SIZE_NONE,
- STORE_SIZE_BYTE,
- STORE_SIZE_WORD,
- STORE_SIZE_DWORD,
- STORE_SIZE_QWORD,
-};
-
-struct ConstDecl
-{
- struct Token name;
- struct Expr* value;
-};
-
-struct DataDecl
-{
- struct Token name;
- struct Token value;
-};
-
-struct EnumDecl
-{
- struct Token name;
- struct Token* members;
- size_t member_count;
- size_t member_capacity;
-};
-
-struct StructField
-{
- struct Token name;
- enum StoreSize size;
-};
-
-struct StructDecl
-{
- struct Token name;
- struct StructField* fields;
- size_t field_count;
- size_t field_capacity;
-};
-
-struct Param
-{
- struct Token name;
- struct Token reg;
-};
-
-enum ExprKind
-{
- EXPR_PRIMARY,
- EXPR_UNARY,
- EXPR_BINARY,
- EXPR_MEMBER,
- EXPR_DEREF,
-};
-
-struct PrimaryExpr
-{
- struct Token token;
-};
-
-struct UnaryExpr
-{
- struct Token op;
- struct Expr* operand;
-};
-
-struct BinaryExpr
-{
- struct Expr* left;
- struct Token op;
- struct Expr* right;
-};
-
-struct MemberExpr
-{
- struct Expr* object;
- struct Token member;
-};
-
-struct DerefExpr
-{
- bool is_signed;
- enum StoreSize size;
- struct Expr* address;
-};
-
-struct Expr
-{
- enum ExprKind kind;
- union
- {
- struct PrimaryExpr primary;
- struct UnaryExpr unary;
- struct BinaryExpr binary;
- struct MemberExpr member;
- struct DerefExpr deref;
- };
-};
-
-enum StatementKind
-{
- STATEMENT_ASSIGN,
- STATEMENT_LABEL,
- STATEMENT_GOTO,
- STATEMENT_SYSCALL,
- STATEMENT_IF,
- STATEMENT_CALL,
- STATEMENT_STACK,
-};
-
-struct AssignStatement
-{
- bool target_deref;
- enum StoreSize store_size;
- struct Token target;
- struct Token op;
- struct Expr* value;
-};
-
-struct LabelStatement
-{
- struct Token name;
-};
-
-struct GotoStatement
-{
- struct Token label;
-};
-
-struct IfStatement
-{
- struct Expr* left;
- struct Token comparison;
- struct Expr* right;
- struct Statement* body;
- size_t body_count;
- struct Statement* else_body;
- size_t else_count;
-};
-
-struct CallStatement
-{
- struct Token name;
- struct Expr** args;
- size_t arg_count;
- size_t arg_capacity;
-};
-
-struct StackStatement
-{
- struct Token name;
- struct Expr* size;
-};
-
-struct Statement
-{
- enum StatementKind kind;
- union
- {
- struct AssignStatement assign;
- struct LabelStatement label;
- struct GotoStatement jump;
- struct IfStatement branch;
- struct CallStatement call;
- struct StackStatement stack;
- };
-};
-
-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 Config
-{
- uint32_t bits;
- bool has_entry;
- struct Token entry;
- bool logical_registers;
-};
-
-struct Program
-{
- struct Config config;
-
- struct ConstDecl* consts;
- size_t const_count;
- size_t const_capacity;
-
- struct DataDecl* data_decls;
- size_t data_count;
- size_t data_capacity;
-
- struct EnumDecl* enums;
- size_t enum_count;
- size_t enum_capacity;
-
- struct StructDecl* structs;
- size_t struct_count;
- size_t struct_capacity;
-
- struct ProcDecl* procs;
- size_t proc_count;
- size_t proc_capacity;
-};
-
-struct Program create_program(void);
-void free_program(struct Program* program);
-void add_const(struct Program* program, struct ConstDecl decl);
-void add_data(struct Program* program, struct DataDecl decl);
-
-struct EnumDecl create_enum(void);
-void add_enum_member(struct EnumDecl* decl, struct Token member);
-void add_enum(struct Program* program, struct EnumDecl decl);
-
-struct StructDecl create_struct(void);
-void add_struct_field(struct StructDecl* decl, struct StructField field);
-void add_struct(struct Program* program, struct StructDecl decl);
-
-struct ProcDecl create_proc(void);
-void free_proc(struct ProcDecl* proc);
-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);
-
-void free_expr(struct Expr* expr);
-void free_statement(struct Statement* statement);
diff --git a/src/parser/parser.c b/src/parser/parser.c
deleted file mode 100644
index 97b8569..0000000
--- a/src/parser/parser.c
+++ /dev/null
@@ -1,787 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "diag/diag.h"
-#include "parser/parser.h"
-
-struct Parser
-{
- struct Lexer* lexer;
- struct Source source;
- 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)
-{
- report_error(parser->source, token, message);
- 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))
- {
- advance_parser(parser);
- return true;
- }
-
- error_at(parser, parser->current, message);
- return false;
-}
-
-static struct Expr* parse_expression(struct Parser* parser);
-static enum StoreSize parse_store_size(struct Parser* parser);
-
-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;
-
- decl.value = parse_expression(parser);
- if (decl.value == NULL)
- return false;
-
- add_const(program, decl);
- return true;
-}
-
-static bool parse_data(struct Parser* parser, struct Program* program)
-{
- struct DataDecl decl;
-
- if (!consume(parser, TOKEN_IDENTIFIER, "expected data name after 'data'"))
- return false;
- decl.name = parser->previous;
-
- if (!consume(parser, TOKEN_EQUAL, "expected '=' after data name"))
- return false;
-
- if (!consume(parser, TOKEN_STRING, "expected string value after '='"))
- return false;
- decl.value = parser->previous;
-
- add_data(program, decl);
- return true;
-}
-
-static bool parse_enum(struct Parser* parser, struct Program* program)
-{
- struct EnumDecl decl = create_enum();
-
- if (!consume(parser, TOKEN_IDENTIFIER, "expected enum name after 'enum'"))
- goto error;
- decl.name = parser->previous;
-
- if (!consume(parser, TOKEN_LEFT_BRACE, "expected '{' after enum name"))
- goto error;
-
- while (!check(parser, TOKEN_RIGHT_BRACE))
- {
- if (check(parser, TOKEN_EOF))
- {
- error_at(parser, parser->current, "unterminated enum");
- goto error;
- }
-
- if (!consume(parser, TOKEN_IDENTIFIER, "expected an enum member name"))
- goto error;
- add_enum_member(&decl, parser->previous);
-
- match_token(parser, TOKEN_COMMA);
- }
- advance_parser(parser);
-
- add_enum(program, decl);
- return true;
-
-error:
- free(decl.members);
- return false;
-}
-
-static bool parse_struct(struct Parser* parser, struct Program* program)
-{
- struct StructDecl decl = create_struct();
-
- if (!consume(parser, TOKEN_IDENTIFIER, "expected struct name after 'struct'"))
- goto error;
- decl.name = parser->previous;
-
- if (!consume(parser, TOKEN_LEFT_BRACE, "expected '{' after struct name"))
- goto error;
-
- while (!check(parser, TOKEN_RIGHT_BRACE))
- {
- if (check(parser, TOKEN_EOF))
- {
- error_at(parser, parser->current, "unterminated struct");
- goto error;
- }
-
- struct StructField field;
- if (!consume(parser, TOKEN_IDENTIFIER, "expected a field name"))
- goto error;
- field.name = parser->previous;
-
- field.size = STORE_SIZE_QWORD;
- if (match_token(parser, TOKEN_COLON))
- {
- field.size = parse_store_size(parser);
- if (field.size == STORE_SIZE_NONE)
- {
- error_at(parser, parser->current, "expected a size (byte, word, dword, qword) after ':'");
- goto error;
- }
- }
-
- add_struct_field(&decl, field);
- match_token(parser, TOKEN_COMMA);
- }
- advance_parser(parser);
-
- add_struct(program, decl);
- return true;
-
-error:
- free(decl.fields);
- return false;
-}
-
-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 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
- || type == TOKEN_PERCENT_EQUAL;
-}
-
-static struct Expr* alloc_expr(enum ExprKind kind)
-{
- struct Expr* expr = malloc(sizeof(*expr));
- if (expr != NULL)
- expr->kind = kind;
- return expr;
-}
-
-static enum StoreSize parse_store_size(struct Parser* parser)
-{
- if (match_token(parser, TOKEN_BYTE))
- return STORE_SIZE_BYTE;
- if (match_token(parser, TOKEN_WORD))
- return STORE_SIZE_WORD;
- if (match_token(parser, TOKEN_DWORD))
- return STORE_SIZE_DWORD;
- if (match_token(parser, TOKEN_QWORD))
- return STORE_SIZE_QWORD;
- return STORE_SIZE_NONE;
-}
-
-static struct Expr* parse_primary(struct Parser* parser)
-{
- if (match_token(parser, TOKEN_CARET))
- {
- bool is_signed = match_token(parser, TOKEN_SIGNED);
- enum StoreSize size = parse_store_size(parser);
-
- struct Expr* address = parse_primary(parser);
- if (address == NULL)
- return NULL;
-
- struct Expr* deref = alloc_expr(EXPR_DEREF);
- if (deref == NULL)
- {
- free_expr(address);
- return NULL;
- }
- deref->deref.is_signed = is_signed;
- deref->deref.size = size;
- deref->deref.address = address;
- return deref;
- }
-
- if (check(parser, TOKEN_IDENTIFIER) || check(parser, TOKEN_INTEGER)
- || check(parser, TOKEN_FLOAT) || check(parser, TOKEN_CHAR))
- {
- advance_parser(parser);
-
- struct Expr* expr = alloc_expr(EXPR_PRIMARY);
- expr->primary.token = parser->previous;
- return expr;
- }
-
- error_at(parser, parser->current, "expected an expression");
- return NULL;
-}
-
-static struct Expr* parse_postfix(struct Parser* parser)
-{
- struct Expr* expr = parse_primary(parser);
- if (expr == NULL)
- return NULL;
-
- while (match_token(parser, TOKEN_DOT))
- {
- // an identifier is a member (data.len); an integer is a register size
- // suffix (r1.64), meaningful with the logical_registers extension
- if (!check(parser, TOKEN_IDENTIFIER) && !check(parser, TOKEN_INTEGER))
- {
- error_at(parser, parser->current, "expected a member name or size after '.'");
- free_expr(expr);
- return NULL;
- }
- advance_parser(parser);
-
- struct Expr* member = alloc_expr(EXPR_MEMBER);
- member->member.object = expr;
- member->member.member = parser->previous;
- expr = member;
- }
-
- return expr;
-}
-
-static struct Expr* parse_unary(struct Parser* parser)
-{
- if (match_token(parser, TOKEN_MINUS))
- {
- struct Token op = parser->previous;
-
- struct Expr* operand = parse_unary(parser);
- if (operand == NULL)
- return NULL;
-
- struct Expr* expr = alloc_expr(EXPR_UNARY);
- if (expr == NULL)
- {
- free_expr(operand);
- return NULL;
- }
- expr->unary.op = op;
- expr->unary.operand = operand;
- return expr;
- }
-
- return parse_postfix(parser);
-}
-
-static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*),
- enum TokenType a, enum TokenType b, enum TokenType c)
-{
- struct Expr* left = operand(parser);
- if (left == NULL)
- return NULL;
-
- while (check(parser, a) || check(parser, b) || check(parser, c))
- {
- advance_parser(parser);
- struct Token op = parser->previous;
-
- struct Expr* right = operand(parser);
- if (right == NULL)
- {
- free_expr(left);
- return NULL;
- }
-
- struct Expr* binary = alloc_expr(EXPR_BINARY);
- binary->binary.left = left;
- binary->binary.op = op;
- binary->binary.right = right;
- left = binary;
- }
-
- return left;
-}
-
-static struct Expr* parse_multiplicative(struct Parser* parser)
-{
- return parse_binary(parser, parse_unary, TOKEN_STAR, TOKEN_SLASH, TOKEN_PERCENT);
-}
-
-static struct Expr* parse_expression(struct Parser* parser)
-{
- return parse_binary(parser, parse_multiplicative, TOKEN_PLUS, TOKEN_MINUS, TOKEN_MINUS);
-}
-
-static bool is_compare_op(enum TokenType type)
-{
- return type == TOKEN_EQUAL_EQUAL
- || type == TOKEN_BANG_EQUAL
- || type == TOKEN_LESS
- || type == TOKEN_LESS_EQUAL
- || type == TOKEN_GREATER
- || type == TOKEN_GREATER_EQUAL;
-}
-
-static bool parse_call(struct Parser* parser, struct Token name, struct Statement* out)
-{
- struct Expr** args = NULL;
- size_t count = 0;
- size_t capacity = 0;
-
- if (!check(parser, TOKEN_RIGHT_PAREN))
- {
- do
- {
- struct Expr* arg = parse_expression(parser);
- if (arg == NULL)
- goto error;
-
- if (count == capacity)
- {
- capacity = capacity < 4 ? 4 : capacity * 2;
- struct Expr** grown = realloc(args, capacity * sizeof(struct Expr*));
- if (grown == NULL)
- {
- free_expr(arg);
- goto error;
- }
- args = grown;
- }
- args[count] = arg;
- count += 1;
- }
- while (match_token(parser, TOKEN_COMMA));
- }
-
- if (!consume(parser, TOKEN_RIGHT_PAREN, "expected ')' after arguments"))
- goto error;
-
- out->kind = STATEMENT_CALL;
- out->call.name = name;
- out->call.args = args;
- out->call.arg_count = count;
- out->call.arg_capacity = capacity;
- return true;
-
-error:
- for (size_t i = 0; i < count; i += 1)
- free_expr(args[i]);
- free(args);
- return false;
-}
-
-static bool parse_statement(struct Parser* parser, struct Statement* out);
-
-// A branch body is either a braced block or a single bare statement, always
-// returned as a list so codegen and freeing treat both the same way.
-static bool parse_block(struct Parser* parser, struct Statement** out_body, size_t* out_count)
-{
- if (!match_token(parser, TOKEN_LEFT_BRACE))
- {
- struct Statement* body = malloc(sizeof(*body));
- if (body == NULL)
- return false;
-
- if (!parse_statement(parser, body))
- {
- free(body);
- return false;
- }
-
- *out_body = body;
- *out_count = 1;
- return true;
- }
-
- struct Statement* body = NULL;
- size_t count = 0;
- size_t capacity = 0;
-
- while (!check(parser, TOKEN_RIGHT_BRACE))
- {
- if (check(parser, TOKEN_EOF))
- {
- error_at(parser, parser->current, "unterminated block");
- goto error;
- }
-
- if (count == capacity)
- {
- size_t grown_capacity = capacity == 0 ? 4 : capacity * 2;
- struct Statement* grown = realloc(body, grown_capacity * sizeof(*grown));
- if (grown == NULL)
- goto error;
- body = grown;
- capacity = grown_capacity;
- }
-
- if (!parse_statement(parser, &body[count]))
- goto error;
- count += 1;
- }
- advance_parser(parser);
-
- *out_body = body;
- *out_count = count;
- return true;
-
-error:
- for (size_t i = 0; i < count; i += 1)
- free_statement(&body[i]);
- free(body);
- return false;
-}
-
-static bool parse_if(struct Parser* parser, struct Statement* out)
-{
- struct Expr* left = parse_expression(parser);
- if (left == NULL)
- return false;
-
- if (!is_compare_op(parser->current.type))
- {
- error_at(parser, parser->current, "expected a comparison operator");
- free_expr(left);
- return false;
- }
- advance_parser(parser);
- struct Token comparison = parser->previous;
-
- struct Expr* right = parse_expression(parser);
- if (right == NULL)
- {
- free_expr(left);
- return false;
- }
-
- struct Statement* body;
- size_t body_count;
- if (!parse_block(parser, &body, &body_count))
- {
- free_expr(left);
- free_expr(right);
- return false;
- }
-
- struct Statement* else_body = NULL;
- size_t else_count = 0;
- if (match_token(parser, TOKEN_ELSE) && !parse_block(parser, &else_body, &else_count))
- {
- for (size_t i = 0; i < body_count; i += 1)
- free_statement(&body[i]);
- free(body);
- free_expr(left);
- free_expr(right);
- return false;
- }
-
- out->kind = STATEMENT_IF;
- out->branch.left = left;
- out->branch.comparison = comparison;
- out->branch.right = right;
- out->branch.body = body;
- out->branch.body_count = body_count;
- out->branch.else_body = else_body;
- out->branch.else_count = else_count;
- return true;
-}
-
-static bool parse_statement(struct Parser* parser, struct Statement* out)
-{
- if (match_token(parser, TOKEN_IF))
- return parse_if(parser, out);
-
- if (match_token(parser, TOKEN_SYSCALL))
- {
- out->kind = STATEMENT_SYSCALL;
- return true;
- }
-
- if (match_token(parser, TOKEN_STACK))
- {
- if (!consume(parser, TOKEN_IDENTIFIER, "expected buffer name after 'stack'"))
- return false;
- struct Token name = parser->previous;
-
- if (!consume(parser, TOKEN_LEFT_BRACKET, "expected '[' after buffer name"))
- return false;
-
- struct Expr* size = parse_expression(parser);
- if (size == NULL)
- return false;
-
- if (!consume(parser, TOKEN_RIGHT_BRACKET, "expected ']' after buffer size"))
- {
- free_expr(size);
- return false;
- }
-
- out->kind = STATEMENT_STACK;
- out->stack.name = name;
- out->stack.size = size;
- return true;
- }
-
- if (match_token(parser, TOKEN_GOTO))
- {
- if (!consume(parser, TOKEN_IDENTIFIER, "expected label after 'goto'"))
- return false;
-
- out->kind = STATEMENT_GOTO;
- out->jump.label = parser->previous;
- return true;
- }
-
- bool deref = match_token(parser, TOKEN_CARET);
- enum StoreSize store_size = deref ? parse_store_size(parser) : STORE_SIZE_NONE;
-
- if (!consume(parser, TOKEN_IDENTIFIER, "expected a statement"))
- return false;
- struct Token name = parser->previous;
-
- if (!deref && match_token(parser, TOKEN_LEFT_PAREN))
- return parse_call(parser, name, out);
-
- if (!deref && match_token(parser, TOKEN_COLON))
- {
- out->kind = STATEMENT_LABEL;
- out->label.name = name;
- return true;
- }
-
- if (!is_assign_op(parser->current.type))
- {
- error_at(parser, parser->current, "expected an assignment operator");
- return false;
- }
-
- advance_parser(parser);
- struct Token op = parser->previous;
-
- struct Expr* value = parse_expression(parser);
- if (value == NULL)
- return false;
-
- out->kind = STATEMENT_ASSIGN;
- out->assign.target_deref = deref;
- out->assign.store_size = store_size;
- out->assign.target = name;
- out->assign.op = op;
- out->assign.value = value;
- 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;
-
- while (!check(parser, TOKEN_RIGHT_BRACE))
- {
- if (check(parser, TOKEN_EOF))
- {
- error_at(parser, parser->current, "unterminated procedure body");
- goto error;
- }
-
- 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_proc(&decl);
- return false;
-}
-
-static bool token_text_is(struct Token token, const char* text)
-{
- size_t length = strlen(text);
- return token.length == length && memcmp(token.start, text, length) == 0;
-}
-
-static bool parse_directive(struct Parser* parser, struct Program* program)
-{
- if (!consume(parser, TOKEN_IDENTIFIER, "expected directive name after '['"))
- return false;
- struct Token key = parser->previous;
-
- if (!consume(parser, TOKEN_COLON, "expected ':' after directive name"))
- return false;
-
- if (!check(parser, TOKEN_IDENTIFIER) && !check(parser, TOKEN_INTEGER))
- {
- error_at(parser, parser->current, "expected a directive value");
- return false;
- }
- advance_parser(parser);
- struct Token value = parser->previous;
-
- if (!consume(parser, TOKEN_RIGHT_BRACKET, "expected ']' to close directive"))
- return false;
-
- if (token_text_is(key, "bits"))
- {
- if (value.type != TOKEN_INTEGER || (!token_text_is(value, "64") && !token_text_is(value, "32")))
- {
- error_at(parser, value, "bits must be 32 or 64");
- return false;
- }
- program->config.bits = token_text_is(value, "64") ? 64 : 32;
- return true;
- }
-
- if (token_text_is(key, "entry"))
- {
- if (value.type != TOKEN_IDENTIFIER)
- {
- error_at(parser, value, "entry must be a procedure name");
- return false;
- }
- program->config.has_entry = true;
- program->config.entry = value;
- return true;
- }
-
- if (token_text_is(key, "enable"))
- {
- if (value.type == TOKEN_IDENTIFIER && token_text_is(value, "logical_registers"))
- {
- program->config.logical_registers = true;
- return true;
- }
- error_at(parser, value, "unknown extension");
- return false;
- }
-
- error_at(parser, key, "unknown directive");
- return false;
-}
-
-bool parse_program(struct Lexer* lexer, struct Program* out)
-{
- struct Parser parser = { 0 };
- parser.lexer = lexer;
- parser.source.name = lexer->name;
- parser.source.text = lexer->source;
- parser.had_error = false;
- advance_parser(&parser);
-
- *out = create_program();
-
- while (!check(&parser, TOKEN_EOF))
- {
- if (check(&parser, TOKEN_LEFT_BRACKET))
- {
- advance_parser(&parser);
- if (!parse_directive(&parser, out))
- return false;
- }
- else if (check(&parser, TOKEN_CONST))
- {
- advance_parser(&parser);
- if (!parse_const(&parser, out))
- return false;
- }
- else if (check(&parser, TOKEN_DATA))
- {
- advance_parser(&parser);
- if (!parse_data(&parser, out))
- return false;
- }
- else if (check(&parser, TOKEN_ENUM))
- {
- advance_parser(&parser);
- if (!parse_enum(&parser, out))
- return false;
- }
- else if (check(&parser, TOKEN_STRUCT))
- {
- advance_parser(&parser);
- if (!parse_struct(&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");
- return false;
- }
- }
-
- return !parser.had_error;
-}
diff --git a/src/parser/parser.h b/src/parser/parser.h
deleted file mode 100644
index 82d306a..0000000
--- a/src/parser/parser.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-
-#include "lexer/lexer.h"
-#include "parser/ast.h"
-
-bool parse_program(struct Lexer* lexer, struct Program* out);