#include #include #include #include #include "parse.h" #include "lex.h" int next_token(struct parser *parser, struct token *tok) { if (parser->peek.type != TOK_EOF) { if (tok != NULL) *tok = parser->peek; parser->peek.type = TOK_EOF; return M_SUCCESS; } struct token token; if (lexer_next(parser->lexer, &token)) return M_ERROR; if (tok != NULL) *tok = token; return M_SUCCESS; } int peek_token(struct parser *parser, struct token *tok) { if (parser->peek.type == TOK_EOF) { if (next_token(parser, &parser->peek)) return M_ERROR; } if (tok != NULL) *tok = parser->peek; return M_SUCCESS; } int assert_token(struct parser *parser, enum token_type type, struct token *tok) { struct token token; if (next_token(parser, &token)) return M_ERROR; if (token.type != type) { ERROR_POS(token, "expected a token of type '%s', got '%s'", token_str(type), token_str(token.type)); return M_ERROR; } if (tok != NULL) *tok = token; return M_SUCCESS; } int assert_eol(struct parser *parser) { struct token token; if (next_token(parser, &token)) return M_ERROR; if (token.type != TOK_NL && token.type != TOK_EOF) { ERROR_POS(token, "expected a new line or end of file"); return M_ERROR; } return M_SUCCESS; } static int parse_constant(struct parser *parser, struct const_expr *expr, struct token ident) { struct token number; if (assert_token(parser, TOK_EQUAL, NULL)) return M_ERROR; if (assert_token(parser, TOK_NUMBER, &number)) return M_ERROR; strcpy(expr->name,ident.text); expr->value = number.number; return M_SUCCESS; } static int parser_handle_ident(struct parser *parser, struct expr *expr) { struct token ident; struct token peek; if (assert_token(parser, TOK_IDENT, &ident)) return M_ERROR; if (peek_token(parser, &peek)) return M_ERROR; if (peek.type == TOK_EQUAL) { expr->type = EXPR_CONSTANT; return parse_constant(parser, &expr->constant, ident); } else { expr->type = EXPR_INS; return parser->parse_instruction(parser, &expr->ins, ident); } } static int parse_label(struct parser *parser, struct expr *expr) { struct token token; if (assert_token(parser, TOK_LABEL, &token)) return M_ERROR; strcpy(expr->text, token.text); struct symbol *ref; if (symtbl_find(&parser->sym_tbl, &ref, token.text) == M_SUCCESS) { if (ref->flag == SYM_GLOBAL && ref->sec == NULL) { ref->sec = parser->sec_tbl.current; ref->index = parser->sec_tbl.current->count; return M_SUCCESS; } ERROR_POS(token, "redefined symbol '%s'", token.text); return M_ERROR; } struct symbol symbol; symbol = (struct symbol) { .name = "", .sec = parser->sec_tbl.current, .index = parser->sec_tbl.current->count, .flag = SYM_LOCAL, }; strcpy(symbol.name, token.text); if (symtbl_push(&parser->sym_tbl, symbol)) return M_ERROR; return M_SUCCESS; } int parser_next(struct parser *parser, struct expr *expr) { struct token token; int res = M_SUCCESS; again: if (peek_token(parser, &token)) return M_ERROR; switch (token.type) { case TOK_NL: next_token(parser, NULL); goto again; case TOK_EOF: res = M_EOF; break; case TOK_LABEL: expr->type = EXPR_LABEL; res = parse_label(parser, expr); break; case TOK_DIRECTIVE: expr->type = EXPR_DIRECTIVE; res = parser->parse_directive(parser, &expr->directive); break; case TOK_IDENT: res = parser_handle_ident(parser, expr); break; default: ERROR_POS(token, "unexpected token '%s'", token_str(token.type)); return M_ERROR; } return res; } int parser_init(struct lexer *lexer, struct parser *parser) { parser->lexer = lexer; parser->peek.type = TOK_EOF; if (symtbl_init(&parser->sym_tbl)) return M_ERROR; if (sectbl_init(&parser->sec_tbl)) return M_ERROR; if (reftbl_init(&parser->ref_tbl)) return M_ERROR; return M_SUCCESS; } void parser_free(struct parser *parser) { symtbl_free(&parser->sym_tbl); sectbl_free(&parser->sec_tbl); reftbl_free(&parser->ref_tbl); }