#include #include #include #include "parser.h" /* Vrátí ukazatel na aktuální token */ static const struct token *get_token(const struct parser *parser) { return lex_token(&parser->lexer); } /* Vrátí 1, pokud aktuální token je typu */ static int token_is(const struct parser *parser, enum token_type type) { return get_token(parser)->type == type; } /* Vrátí hodnotu tokenu, který je konstanta */ static double token_num(const struct parser *parser) { return get_token(parser)->val.num; } /* Vrátí index funkce tokenu, který reprezentuje funkci */ static size_t token_fn_idx(const struct parser *parser) { return get_token(parser)->val.fn_idx; } /* Načte další token */ static void next_token(struct parser *parser) { lex_next(&parser->lexer); } /* Vrátí 1, pokud je aktuální token typu a načte další */ static int accept_token(struct parser *parser, enum token_type type) { if (token_is(parser, type)) { next_token(parser); return 1; } return 0; } /* Nastaví chybu při alokaci */ static void error_bad_alloc(struct parser *parser) { error_set(&parser->eb, ERR_BAD_ALLOC); error_printf(&parser->eb, "Out of memory\n"); } /* Vyhodí chybu při neočekávaném tokenu */ static void error_expected_tokens(struct parser *parser, size_t num_tokens, ...) { size_t i; va_list ap; 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, "%s", lex_get_error_text(&parser->lexer)); return; } error_set(&parser->eb, ERR_INVALID_FUNCTION); error_printf(&parser->eb, "Syntax error - expected "); va_start(ap, num_tokens); for (i = 0; i < num_tokens; ++i) { enum token_type tok = va_arg(ap, enum token_type); if (i > 0) error_printf(&parser->eb, ", "); error_printf(&parser->eb, "%s", lex_token_str(tok)); } va_end(ap); error_printf(&parser->eb, " - but got %s\n", lex_token_str(got)); lex_print_position(&parser->lexer, &parser->eb); } static struct expr_node *parse_expression(struct parser *parser); static int parse_n_expressions(struct parser *parser, struct expr_node **out_nodes, size_t n); /* Zpracuje výraz obalený závorkami */ static struct expr_node *parse_bracketed(struct parser *parser) { struct expr_node *node; if (!accept_token(parser, TOK_LEFT_PAREN)) { error_expected_tokens(parser, 1, TOK_LEFT_PAREN); return NULL; } if (!(node = parse_expression(parser))) return NULL; if (!accept_token(parser, TOK_RIGHT_PAREN)) { error_expected_tokens(parser, 1, TOK_RIGHT_PAREN); node_free(node); return NULL; } return node; } static struct expr_node *parse_function(struct parser *parser) { struct expr_node *node; struct expr_node *arg_nodes[MAX_MATH_FUNCTION_ARGS]; size_t i; size_t fn_idx = token_fn_idx(parser); const struct math_function *fn = &fns_get()[fn_idx]; next_token(parser); if (!accept_token(parser, TOK_LEFT_PAREN)) { error_expected_tokens(parser, 1, TOK_LEFT_PAREN); return NULL; } if (!parse_n_expressions(parser, arg_nodes, fn->num_args)) return NULL; if (!(node = node_create_fn(fn_idx, arg_nodes))) { error_bad_alloc(parser); for (i = 0; i < fn->num_args; ++i) node_free(arg_nodes[i]); return NULL; } if (!accept_token(parser, TOK_RIGHT_PAREN)) { error_expected_tokens(parser, 1, TOK_RIGHT_PAREN); node_free(node); return NULL; } return node; } /* Zpracuje část výrazu, která už má nejvyšší precedenci (číselnou konstantu, proměnnou, funkci, nebo výraz obalený závorkami) */ static struct expr_node *parse_factor(struct parser *parser) { struct expr_node *node; 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_VARIABLE)) { if (!(node = node_create_x())) { error_bad_alloc(parser); return NULL; } return node; } if (token_is(parser, TOK_FUNCTION)) { return parse_function(parser); } if (token_is(parser, TOK_LEFT_PAREN)) { return parse_bracketed(parser); } error_expected_tokens(parser, 4, TOK_NUMBER, TOK_VARIABLE, TOK_FUNCTION, TOK_LEFT_PAREN); return NULL; } static struct expr_node *parse_unary(struct parser *parser); /* Zpracuje umocnění */ static struct expr_node *parse_power(struct parser *parser) { struct expr_node *node, *new_node, *inner; if (!(node = parse_factor(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; } /* Zpracuje unární mínus, resp. plus */ static struct expr_node *parse_unary(struct parser *parser) { if (accept_token(parser, TOK_MINUS)) { struct expr_node *node, *inner; if (!(inner = parse_power(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_power(parser); } /* Zpracuje součin nebo dělení */ 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; } /* Zpracuje sčítání nebo odečítání */ static struct expr_node *parse_expression(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; } /* Zpracuje n výrazů */ static int parse_n_expressions(struct parser *parser, struct expr_node **out_nodes, size_t n) { size_t i; for (i = 0; i < n; ++i) { struct expr_node *node; if (!(node = parse_expression(parser))) break; out_nodes[i] = node; if (i < n - 1) accept_token(parser, TOK_COMMA); } if (i != n) { while (i) { --i; node_free(out_nodes[i]); out_nodes[i] = NULL; } return 0; } return 1; } int parser_parse_n(struct parser *parser, const char *str, const char *variable_name, struct expr_node **out_nodes, size_t n) { error_buffer_init(&parser->eb); lex_init(&parser->lexer, str, variable_name); if (!parse_n_expressions(parser, out_nodes, n)) { return 0; } if (!token_is(parser, TOK_EOF)) { size_t i; error_expected_tokens(parser, 1, TOK_EOF); for (i = 0; i < n; ++i) { node_free(out_nodes[i]); out_nodes[i] = NULL; } return 0; } return 1; } struct expr_node *parser_parse(struct parser *parser, const char *str, const char *variable_name) { struct expr_node *out_node = NULL; parser_parse_n(parser, str, variable_name, &out_node, 1); return out_node; } 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); }