#include #include #include "parser.h" static struct token *get_token(struct parser *parser) { return lex_token(&parser->lexer); } static int token_is(struct parser *parser, enum token_type type) { return get_token(parser)->type == type; } static double token_num(struct parser *parser) { return get_token(parser)->val.num; } static enum math_fn token_fn(struct parser *parser) { return get_token(parser)->val.fn; } static void next_token(struct parser *parser) { lex_next(&parser->lexer); } static int accept_token(struct parser *parser, enum token_type type) { if (token_is(parser, type)) { next_token(parser); return 1; } return 0; } static void error_bad_alloc(struct parser *parser) { error_set(&parser->eb, ERR_BAD_ALLOC); error_printf(&parser->eb, "Out of memory\n"); } static void error_expected_one_of(struct parser *parser, const int expected[]) { static const char* token_name[] = { "end of expression", "lexer error", "constant", "+", "-", "*", "/", "^", "x", "function name", "(", ")" }; size_t i; enum token_type got = get_token(parser)->type; if (got == TOK_ERROR) { error_set(&parser->eb, lex_get_error(&parser->lexer)); error_printf(&parser->eb, "Lexer error - %s", lex_get_error_text(&parser->lexer)); return; } error_set(&parser->eb, ERR_INVALID_FUNCTION); error_printf(&parser->eb, "Syntax error - expected "); for (i = 0; expected[i] >= 0; ++i) { if (i > 0) error_printf(&parser->eb, ", "); error_printf(&parser->eb, "'%s'", token_name[expected[i]]); } error_printf(&parser->eb, " - but got '%s'\n", token_name[got]); lex_print_position(&parser->lexer, &parser->eb); } static void error_expected_single(struct parser *parser, enum token_type expected) { static int expected_arr[] = { -1, -1 }; expected_arr[0] = expected; error_expected_one_of(parser, expected_arr); } static struct expr_node* parse_subexpression(struct parser *parser); static struct expr_node* parse_bracketed(struct parser *parser) { struct expr_node* node; if (!accept_token(parser, TOK_LEFT_PAREN)) { error_expected_single(parser, TOK_LEFT_PAREN); return NULL; } if (!(node = parse_subexpression(parser))) return NULL; if (!accept_token(parser, TOK_RIGHT_PAREN)) { error_expected_single(parser, TOK_RIGHT_PAREN); node_free(node); return NULL; } return node; } static struct expr_node *parse_base(struct parser *parser) { struct expr_node *node, *inner; if (token_is(parser, TOK_NUMBER)) { double val = token_num(parser); next_token(parser); if (!(node = node_create_const(val))) { error_bad_alloc(parser); return NULL; } return node; } if (accept_token(parser, TOK_X)) { if (!(node = node_create_x())) { error_bad_alloc(parser); return NULL; } return node; } if (token_is(parser, TOK_FUNCTION)) { enum math_fn fn = token_fn(parser); next_token(parser); if (!(inner = parse_bracketed(parser))) return NULL; if (!(node = node_create_fn(fn, inner))) { node_free(inner); error_bad_alloc(parser); return NULL; } return node; } if (token_is(parser, TOK_LEFT_PAREN)) { return parse_bracketed(parser); } { static const int expected[] = { TOK_NUMBER, TOK_X, TOK_FUNCTION, TOK_LEFT_PAREN, -1 }; error_expected_one_of(parser, expected); } return NULL; } static struct expr_node *parse_unary(struct parser *parser); static struct expr_node *parse_factor(struct parser *parser) { struct expr_node* node, * new_node, * inner; if (!(node = parse_base(parser))) return NULL; if (accept_token(parser, TOK_POWER)) { if (!(inner = parse_unary(parser))) { node_free(node); return NULL; } if (!(new_node = node_create_pow(node, inner))) { error_bad_alloc(parser); node_free(node); node_free(inner); return NULL; } return new_node; } return node; } static struct expr_node* parse_unary(struct parser *parser) { if (accept_token(parser, TOK_MINUS)) { struct expr_node *node, *inner; if (!(inner = parse_factor(parser))) return NULL; if (!(node = node_create_neg(inner))) { error_bad_alloc(parser); node_free(inner); return NULL; } return node; } accept_token(parser, TOK_PLUS); return parse_factor(parser); } static struct expr_node *parse_term(struct parser *parser) { struct expr_node *node, *new_node, *inner; if (!(node = parse_unary(parser))) return NULL; while (1) { struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right); if (accept_token(parser, TOK_MULTIPLY)) create_node = node_create_mult; else if (accept_token(parser, TOK_DIVIDE)) create_node = node_create_div; else break; if (!(inner = parse_unary(parser))) { node_free(node); return NULL; } if (!(new_node = create_node(node, inner))) { error_bad_alloc(parser); node_free(node); node_free(inner); return NULL; } node = new_node; } return node; } static struct expr_node *parse_subexpression(struct parser *parser) { struct expr_node *node, *new_node, *inner; if (!(node = parse_term(parser))) return NULL; while (1) { struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right); if (accept_token(parser, TOK_PLUS)) create_node = node_create_add; else if (accept_token(parser, TOK_MINUS)) create_node = node_create_sub; else break; if (!(inner = parse_term(parser))) { node_free(node); return NULL; } if (!(new_node = create_node(node, inner))) { error_bad_alloc(parser); node_free(node); node_free(inner); return NULL; } node = new_node; } return node; } static struct expr_node *parse_expression(struct parser *parser) { struct expr_node *node; if (!(node = parse_subexpression(parser))) return NULL; if (!token_is(parser, TOK_EOF)) { error_expected_single(parser, TOK_EOF); node_free(node); return NULL; } return node; } void parser_init(struct parser *parser) { error_buffer_init(&parser->eb); } struct expr_node *parser_parse(struct parser *parser, const char *str) { lex_init(&parser->lexer, str); return parse_expression(parser); } enum error_code parser_get_error(const struct parser *parser) { return error_get(&parser->eb); } const char *parser_get_error_text(const struct parser *parser) { return error_get_text(&parser->eb); }