summaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
author0x221E <0x221E@0xinfinity.dev>2026-04-12 16:24:06 +0200
committer0x221E <0x221E@0xinfinity.dev>2026-04-12 16:24:06 +0200
commit4946ca67cf04845737f0f7f70b5ed27bcfe9a18b (patch)
treee0ce4c11f5b81828da7680143ea444003dd355b3 /src/parser.c
Initial commitHEADmaster
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..5e5485d
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,170 @@
+#include "parser.h"
+
+#include <backend.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "irm.h"
+#include "lex.h"
+
+int parser_within_bounds(struct parser_config *pc)
+{
+ return pc->pos < pc->size && pc->tokens[pc->pos].type != T_EOF;
+}
+
+int parser_within_obounds(struct parser_config *pc, size_t o)
+{
+ return (pc->pos + o) < pc->size && pc->tokens[pc->pos + o].type != T_EOF;
+}
+
+struct token parser_peek(struct parser_config *pc, size_t o)
+{
+ assert(pc != NULL);
+ if(!parser_within_obounds(pc, o)) return pc->tokens[pc->pos];
+ return pc->tokens[pc->pos + o];
+}
+
+void parser_throw(struct parser_config *pc, const char *err)
+{
+ pc->state = PARSER_PANIC;
+ DEBUG("%s", err);
+ irm_panic(&pc->irm);
+}
+
+int parser_expect(struct parser_config *pc, uint64_t type, const char *err)
+{
+ assert(pc != NULL);
+ if(parser_peek(pc, 0).type == type)
+ return 0;
+ parser_throw(pc, err);
+ return 1;
+}
+
+int parser_expect_condthrow(struct parser_config *pc, uint64_t type, const char *err)
+{
+ assert(pc != NULL);
+ if(parser_peek(pc, 0).type == type)
+ return 0;
+ if(err[0] != '\0')
+ parser_throw(pc, err);
+ return 1;
+}
+
+struct token parser_advance(struct parser_config *pc)
+{
+ assert(pc != NULL);
+ if(!parser_within_bounds(pc)) return pc->tokens[pc->pos];
+ pc->pos++;
+ return pc->tokens[pc->pos];
+}
+
+void parser_literal(struct parser_config *pc)
+{
+ assert(pc != NULL);
+
+ struct token t = parser_peek(pc, 0);
+
+ if(t.type == T_NUMBER) {
+ uint64_t a = atoi(t.me.buf);
+ irm_push_64v(&pc->irm, NUMBER64, a);
+ DEBUG("Pushed into the irm: %lld.\n", a);
+ parser_advance(pc);
+ return;
+ }
+
+ parser_throw(pc, "Invalid expression\n");
+}
+
+uint64_t parser_type_to_irm_inst(struct parser_config *pc, uint64_t type)
+{
+ switch(type) {
+ case T_TYPE_G64:
+ return VAR_DECL_QWORD;
+ case T_TYPE_G32:
+ return VAR_DECL_DWORD;
+ case T_TYPE_G16:
+ return VAR_DECL_WORD;
+ case T_TYPE_G8:
+ return VAR_DECL_BYTE;
+ default:
+ parser_throw(pc, "An invalid type detected... defaulting storage to QWORD.");
+ return VAR_DECL_QWORD;
+ }
+}
+
+void parser_assign_stmt(struct parser_config *pc)
+{
+ struct string_view symbol = parser_peek(pc, 0).me;
+ irm_push(&pc->irm, VAR_ASSIGN);
+ irm_push_lookup_sym(&pc->irm, SYM_VAR, symbol);
+ parser_advance(pc);
+ parser_expect(pc, T_EQUAL_SIGN, "Assignment operation requires an equal sign after the symbol.");
+ parser_advance(pc);
+ parser_literal(pc);
+}
+
+void parser_decl_stmt(struct parser_config *pc)
+{
+ struct token t = parser_peek(pc, 0);
+ if(!(t.type & T_TYPE)) {
+ parser_throw(pc, "Declaration statement must begin with a type!");
+ parser_advance(pc);
+ return;
+ }
+
+ uint64_t type = parser_peek(pc, 0).type;
+ irm_push(&pc->irm, parser_type_to_irm_inst(pc, type));
+ parser_advance(pc);
+
+ parser_expect(pc, T_ID, "An identifier must follow a type in a declaration statement.");
+ struct string_view symbol_name = parser_peek(pc, 0).me;
+ irm_push_sym(&pc->irm, SYM_VAR, symbol_name);
+ parser_advance(pc);
+
+ parser_expect(pc, T_EQUAL_SIGN, "Equal sign must be used to assign a value to a locator");
+ parser_advance(pc);
+ parser_literal(pc);
+}
+
+void parser_stmt(struct parser_config *pc)
+{
+ struct token t = parser_peek(pc, 0);
+ if(t.type & T_TYPE) {
+ parser_decl_stmt(pc);
+ } else if(t.type == T_ID) {
+ parser_assign_stmt(pc);
+ } else {
+ parser_throw(pc,
+ "Invalid statement, can only be declaration "
+ "or assignment.");
+ }
+
+ irm_push(&pc->irm, STMT_DONE); // PUSH STATEMENT DONE SIGNAL
+ irm_stmt_done(&pc->irm); // TRIGGER SIGNAL
+
+ parser_expect(pc, T_SEMICOL, "Statement must end with a semicolon.\n");
+ parser_advance(pc);
+}
+
+void parse_compound_stmt(struct parser_config *pc)
+{
+ assert(pc != NULL);
+
+ irm_stmt_enter_scope(&pc->irm);
+
+ irm_stmt_leave_scope(&pc->irm);
+}
+
+void parser_parse(struct parser_config *pc)
+{
+ assert(pc != NULL);
+ pc->state = PARSER_GRACEFUL;
+
+ irm_init(&pc->irm);
+
+ while(parser_within_bounds(pc)) {
+ parser_stmt(pc);
+ }
+}