#include "parser.h" #include #include #include #include #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); } }