269 lines
6.2 KiB
C
269 lines
6.2 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#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 *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;
|
|
|
|
if (!(node = node_create_fn(fn, inner))) {
|
|
node_free(inner);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
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;
|
|
} |