PC_graph/parser.c
2024-11-28 14:49:19 +01:00

303 lines
7.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#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);
}