aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c3
-rw-r--r--src/parser/ast.h11
-rw-r--r--src/parser/parser.c73
3 files changed, 86 insertions, 1 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
index 1aa1d38..96ee479 100644
--- a/src/parser/ast.c
+++ b/src/parser/ast.c
@@ -58,6 +58,9 @@ void free_proc(struct ProcDecl* proc)
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;
diff --git a/src/parser/ast.h b/src/parser/ast.h
index 6071c4a..a98f43b 100644
--- a/src/parser/ast.h
+++ b/src/parser/ast.h
@@ -1,6 +1,7 @@
#pragma once
#include <stddef.h>
+#include <stdint.h>
#include <stdbool.h>
#include "lexer/lexer.h"
@@ -146,8 +147,18 @@ struct ProcDecl
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;
diff --git a/src/parser/parser.c b/src/parser/parser.c
index ca14023..8603c46 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "parser/parser.h"
@@ -436,6 +437,70 @@ error:
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;
@@ -447,7 +512,13 @@ bool parse_program(struct Lexer* lexer, struct Program* out)
while (!check(&parser, TOKEN_EOF))
{
- if (check(&parser, TOKEN_CONST))
+ 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))