#include #include #include "parser.h" static int token_is(struct lexer *lex, enum token_type type) { return lex_token(lex)->type == type; } static int accept(struct lexer *lex, enum token_type type) { if (token_is(lex, type)) { lex_next(lex); return 1; } return 0; } static double token_num(struct lexer *lex) { return lex_token(lex)->val.num; } static enum math_fn token_fn(struct lexer *lex) { return lex_token(lex)->val.fn; } static void error_expected_one_of(struct lexer *lex, const int expected[], enum token_type got) { static const char* token_name[] = { "end of expression", "lexer error", "constant", "+", "-", "*", "/", "^", "x", "function name", "(", ")" }; int separate = 0; fprintf(stderr, "Syntax error - expected "); for (; *expected >= 0; ++expected) { if (separate) fprintf(stderr, ", "); else separate = 1; fprintf(stderr, "'%s'", token_name[*expected]); } fprintf(stderr, " - but got '%s'\n", token_name[got]); lex_print_position(lex); } static void error_expected_single(struct lexer* lex, enum token_type expected, enum token_type got) { static int expected_arr[] = { -1, -1 }; expected_arr[0] = expected; error_expected_one_of(lex, expected_arr, got); } struct expr_node* parse_subexpression(struct lexer* lex); static struct expr_node* parse_bracketed(struct lexer* lex) { struct expr_node* node; if (!accept(lex, TOK_LEFT_PAREN)) { error_expected_single(lex, TOK_LEFT_PAREN, lex_token(lex)->type); return NULL; } if (!(node = parse_subexpression(lex))) return NULL; if (!accept(lex, TOK_RIGHT_PAREN)) { error_expected_single(lex, TOK_RIGHT_PAREN, lex_token(lex)->type); node_free(node); return NULL; } return node; } static struct expr_node* parse_base(struct lexer* lex) { struct expr_node* inner; if (token_is(lex, TOK_NUMBER)) { double val = token_num(lex); lex_next(lex); return node_create_const(val); } if (accept(lex, TOK_X)) { return node_create_x(); } if (token_is(lex, TOK_FUNCTION)) { enum math_fn fn = token_fn(lex); lex_next(lex); if (!(inner = parse_bracketed(lex))) return NULL; return node_create_fn(fn, inner); } if (token_is(lex, TOK_LEFT_PAREN)) { return parse_bracketed(lex); } { static const int expected[] = { TOK_NUMBER, TOK_X, TOK_FUNCTION, TOK_LEFT_PAREN, -1 }; error_expected_one_of(lex, expected, lex_token(lex)->type); } return NULL; } static struct expr_node* parse_unary(struct lexer* lex); static struct expr_node* parse_factor(struct lexer* lex) { struct expr_node* node, * new_node, * inner; if (!(node = parse_base(lex))) return NULL; if (accept(lex, TOK_POWER)) { if (!(inner = parse_unary(lex))) { node_free(node); return NULL; } if (!(new_node = node_create_pow(node, inner))) { node_free(node); node_free(inner); return NULL; } return new_node; } return node; } static struct expr_node* parse_unary(struct lexer *lex) { if (accept(lex, TOK_MINUS)) { struct expr_node *node, *inner; if (!(inner = parse_factor(lex))) return NULL; if (!(node = node_create_neg(inner))) { node_free(inner); return NULL; } return node; } accept(lex, TOK_PLUS); return parse_factor(lex); } static struct expr_node *parse_term(struct lexer *lex) { struct expr_node *node, *new_node, *inner; if (!(node = parse_unary(lex))) return NULL; while (1) { struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right); if (accept(lex, TOK_MULTIPLY)) create_node = node_create_mult; else if (accept(lex, TOK_DIVIDE)) create_node = node_create_div; else break; if (!(inner = parse_unary(lex))) { node_free(node); return NULL; } if (!(new_node = create_node(node, inner))) { node_free(node); node_free(inner); return NULL; } node = new_node; } return node; } struct expr_node *parse_subexpression(struct lexer *lex) { struct expr_node *node, *new_node, *inner; /* if (accept(lex, TOK_MINUS)) { if (!(term = parse_term(lex))) return NULL; if (!(node = node_create_neg(term))) { node_free(term); return NULL; } } else { accept(lex, TOK_PLUS); if (!(node = parse_term(lex))) return NULL; } */ if (!(node = parse_term(lex))) return NULL; while (1) { struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right); if (accept(lex, TOK_PLUS)) create_node = node_create_add; else if (accept(lex, TOK_MINUS)) create_node = node_create_sub; else break; if (!(inner = parse_term(lex))) { node_free(node); return NULL; } if (!(new_node = create_node(node, inner))) { node_free(node); node_free(inner); return NULL; } node = new_node; } return node; } struct expr_node *parse_expression(struct lexer *lex) { struct expr_node *node; if (!(node = parse_subexpression(lex))) return NULL; if (!token_is(lex, TOK_EOF)) { error_expected_single(lex, TOK_EOF, lex_token(lex)->type); node_free(node); return NULL; } return node; }