#include "parser.h" #include struct ast *parse(enum parser_status *status, struct lexer *lexer) { struct token t = lexer_peek(lexer); *status = PARSER_OK; if (t.type == TOKEN_EOF) { lexer_pop(lexer); return NULL; } else { struct ast *exp = parse_exp(status, lexer); if (*status != PARSER_OK) { return NULL; } struct token t = lexer_pop(lexer); if (*status == PARSER_OK && t.type == TOKEN_EOF) { return exp; } else if (t.type != TOKEN_EOF) { *status = PARSER_UNEXPECTED_TOKEN; fprintf(stderr, "parser: unexpected token\n"); } ast_free(exp); return NULL; } } struct ast *parse_exp(enum parser_status *status, struct lexer *lexer) { struct ast *left = parse_sexp(status, lexer); if (*status == PARSER_UNEXPECTED_TOKEN) return NULL; struct token t = lexer_peek(lexer); if (t.type != TOKEN_PLUS && t.type != TOKEN_MINUS) { *status = PARSER_OK; return left; } else { struct ast *root = left; do { left = root; t = lexer_pop(lexer); if (t.type == TOKEN_PLUS) root = ast_new(AST_PLUS); else root = ast_new(AST_MINUS); root->left = left; root->right = parse_sexp(status, lexer); if (*status == PARSER_UNEXPECTED_TOKEN) { ast_free(root); return NULL; } t = lexer_peek(lexer); } while (t.type != TOKEN_EOF && (t.type == TOKEN_PLUS || t.type == TOKEN_MINUS)); return root; } } struct ast *parse_sexp(enum parser_status *status, struct lexer *lexer) { struct ast *left = parse_texp(status, lexer); if (*status == PARSER_UNEXPECTED_TOKEN) return NULL; struct token t = lexer_peek(lexer); if (t.type != TOKEN_MUL && t.type != TOKEN_DIV) { *status = PARSER_OK; return left; } else { struct ast *root = left; do { left = root; t = lexer_pop(lexer); if (t.type == TOKEN_MUL) root = ast_new(AST_MUL); else root = ast_new(AST_DIV); root->left = left; root->right = parse_texp(status, lexer); if (*status == PARSER_UNEXPECTED_TOKEN) { ast_free(root); return NULL; } t = lexer_peek(lexer); } while (t.type != TOKEN_EOF && (t.type == TOKEN_MUL || t.type == TOKEN_DIV)); return root; } } struct ast *parse_texp(enum parser_status *status, struct lexer *lexer) { struct token t = lexer_pop(lexer); if (t.type == TOKEN_NUMBER) { struct ast *res = ast_new(AST_NUMBER); res->value = t.value; return res; } else if (t.type == TOKEN_MINUS) { t = lexer_peek(lexer); if (t.type != TOKEN_NUMBER && t.type != TOKEN_LEFT_PAR) { *status = PARSER_UNEXPECTED_TOKEN; fprintf(stderr, "parser: unexpected token\n"); return NULL; } struct ast *unary = ast_new(AST_NEG); unary->left = parse_texp(status, lexer); return unary; } else if (t.type == TOKEN_LEFT_PAR) { struct ast *exp = parse_exp(status, lexer); t = lexer_pop(lexer); if (t.type != TOKEN_RIGHT_PAR) { *status = PARSER_UNEXPECTED_TOKEN; fprintf(stderr, "parser: expected closing parenthesis\n"); ast_free(exp); return NULL; } return exp; } else { *status = PARSER_UNEXPECTED_TOKEN; fprintf(stderr, "parser: unexpected token\n"); return NULL; } }