#include #include #include #include #include "array.h" #include "parser.h" #include "lexer.h" #include "string_view.h" void parser_init(parser_t *parser, char *file_name) { assert(parser && file_name); lexer_init(&parser->lexer, file_name); } void parser_next_expected_token(parser_t *parser, token_t *token, token_kind_t kind) { lexer_next_token(&parser->lexer, token); if (token->kind != kind) { fprintf( stderr, "%s:%zu:%zu: parser error: expected token <%s> but got <%s>.\n", parser->lexer.file_name, token->loc.lineno + 1, token->loc.offset - token->loc.lineoffset + 1, token_to_cstr(kind), token_to_cstr(token->kind)); exit(EXIT_FAILURE); } } inst_t * parser_parse(parser_t *parser) { inst_t *insts = array(inst_t); token_t token = { 0 }; int label_count = 0; lexer_next_token(&parser->lexer, &token); while (token.kind != TOKEN_EOF) { switch (token.kind) { case TOKEN_KW_PUSH: { parser_next_expected_token(parser, &token, TOKEN_NUMBER); char value[token.value.size + 1]; value[token.value.size] = '\0'; memcpy(value, token.value.chars, token.value.size); array_append(insts, ((inst_t) { .type = INST_PUSH, .operand = atoi(value) })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_ADD: { array_append(insts, ((inst_t) { .type = INST_ADD })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_DUP: { array_append(insts, ((inst_t) { .type = INST_DUP })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_SWAP: { array_append(insts, ((inst_t) { .type = INST_SWAP })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_SUB: { array_append(insts, ((inst_t) { .type = INST_SUB })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_MUL: { array_append(insts, ((inst_t) { .type = INST_MUL })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_STORE: { array_append(insts, ((inst_t) { .type = INST_STORE })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_LOAD: { array_append(insts, ((inst_t) { .type = INST_LOAD })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_RET: { array_append(insts, ((inst_t) { .type = INST_RET })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_IDENT: { array_append(insts, ((inst_t) { .type = INST_LABEL, .operand = label_count++ })); parser_next_expected_token(parser, &token, TOKEN_COLON); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_JMP: { parser_next_expected_token(parser, &token, TOKEN_NUMBER); char value[token.value.size + 1]; value[token.value.size] = '\0'; memcpy(value, token.value.chars, token.value.size); array_append(insts, ((inst_t) { .type = INST_JMP, .operand = atoi(value) })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_JMPZ: { parser_next_expected_token(parser, &token, TOKEN_NUMBER); char value[token.value.size + 1]; value[token.value.size] = '\0'; memcpy(value, token.value.chars, token.value.size); array_append(insts, ((inst_t) { .type = INST_JMPZ, .operand = atoi(value) })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_CALL: { parser_next_expected_token(parser, &token, TOKEN_NUMBER); char value[token.value.size + 1]; value[token.value.size] = '\0'; memcpy(value, token.value.chars, token.value.size); array_append(insts, ((inst_t) { .type = INST_CALL, .operand = atoi(value) })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_READI: { array_append(insts, ((inst_t) { .type = INST_READI })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_READC: { array_append(insts, ((inst_t) { .type = INST_READC })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_PRINTI: { array_append(insts, ((inst_t) { .type = INST_PRINTI })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_PRINTC: { array_append(insts, ((inst_t) { .type = INST_PRINTC })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_KW_END: { array_append(insts, ((inst_t) { .type = INST_END })); parser_next_expected_token(parser, &token, TOKEN_EOS); break; } case TOKEN_EOS: { break; } default: break; } lexer_next_token(&parser->lexer, &token); } return insts; }