error codes
This commit is contained in:
parent
88c476e052
commit
a62531d893
@ -15,6 +15,7 @@ add_executable(Graph
|
|||||||
"parser.c"
|
"parser.c"
|
||||||
"tree.c"
|
"tree.c"
|
||||||
"ps_graph.c"
|
"ps_graph.c"
|
||||||
|
"error_buffer.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Optionally, you can set compiler warnings
|
# Optionally, you can set compiler warnings
|
||||||
|
|||||||
47
error_buffer.c
Normal file
47
error_buffer.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "error_buffer.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void error_buffer_init(struct error_buffer *eb) {
|
||||||
|
eb->err = ERR_NO_ERR;
|
||||||
|
eb->text_len = 0;
|
||||||
|
eb->text[0] = 0;
|
||||||
|
/* memset(eb->text, 0xAA, MAX_ERROR_MESSAGE_LENGTH); */
|
||||||
|
}
|
||||||
|
|
||||||
|
void error_set(struct error_buffer *eb, enum error_code err) {
|
||||||
|
eb->err = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum error_code error_get(const struct error_buffer *eb) {
|
||||||
|
return eb->err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void error_printf(struct error_buffer *eb, const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
int space = MAX_ERROR_MESSAGE_LENGTH - eb->text_len;
|
||||||
|
int write_size;
|
||||||
|
|
||||||
|
if (space == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
write_size = vsnprintf(eb->text + eb->text_len, MAX_ERROR_MESSAGE_LENGTH - eb->text_len, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (write_size < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (write_size < space) {
|
||||||
|
eb->text_len += write_size;
|
||||||
|
} else {
|
||||||
|
eb->text_len = MAX_ERROR_MESSAGE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eb->text[eb->text_len] = 0; */
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *error_get_text(const struct error_buffer *eb) {
|
||||||
|
return eb->text;
|
||||||
|
}
|
||||||
31
error_buffer.h
Normal file
31
error_buffer.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef ERROR_CODE_H
|
||||||
|
#define ERROR_CODE_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define MAX_ERROR_MESSAGE_LENGTH 512
|
||||||
|
|
||||||
|
enum error_code {
|
||||||
|
ERR_NO_ERR = 0,
|
||||||
|
ERR_INVALID_ARGS = 1,
|
||||||
|
ERR_INVALID_FUNCTION = 2,
|
||||||
|
ERR_INVALID_FILENAME = 3,
|
||||||
|
ERR_INVALID_LIMITS = 4,
|
||||||
|
ERR_BAD_ALLOC = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
struct error_buffer {
|
||||||
|
enum error_code err;
|
||||||
|
char text[MAX_ERROR_MESSAGE_LENGTH];
|
||||||
|
size_t text_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
void error_buffer_init(struct error_buffer *eb);
|
||||||
|
|
||||||
|
void error_set(struct error_buffer *eb, enum error_code err);
|
||||||
|
void error_printf(struct error_buffer *eb, const char *format, ...);
|
||||||
|
|
||||||
|
enum error_code error_get(const struct error_buffer *eb);
|
||||||
|
const char *error_get_text(const struct error_buffer *eb);
|
||||||
|
|
||||||
|
#endif /* ERROR_CODE_H */
|
||||||
66
lex.c
66
lex.c
@ -1,32 +1,16 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "lex.h"
|
#include "lex.h"
|
||||||
|
|
||||||
struct lexer {
|
#include <stdlib.h>
|
||||||
const char* start;
|
#include <stdio.h>
|
||||||
const char* prev_p;
|
#include <string.h>
|
||||||
const char* p;
|
|
||||||
struct token tok;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lexer *lex_create(const char *str) {
|
void lex_init(struct lexer *lex, const char *str) {
|
||||||
struct lexer *lex = malloc(sizeof(struct lexer));
|
error_buffer_init(&lex->eb);
|
||||||
|
|
||||||
if (!lex)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
lex->start = str;
|
lex->start = str;
|
||||||
lex->prev_p = str;
|
lex->prev_p = str;
|
||||||
lex->p = str;
|
lex->p = str;
|
||||||
|
|
||||||
lex_next(lex);
|
lex_next(lex);
|
||||||
|
|
||||||
return lex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lex_free(struct lexer *lex) {
|
|
||||||
free(lex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_whitespace(char p) {
|
static int is_whitespace(char p) {
|
||||||
@ -119,8 +103,9 @@ void lex_next(struct lexer *lex) {
|
|||||||
|
|
||||||
if (try_number(lex)) return;
|
if (try_number(lex)) return;
|
||||||
|
|
||||||
fprintf(stderr, "Lexer error - unrecognized sequence \"%s\"\n", lex->p);
|
error_set(&lex->eb, ERR_INVALID_FUNCTION);
|
||||||
lex_print_position(lex);
|
error_printf(&lex->eb, "Unrecognized sequence \"%s\"\n", lex->p);
|
||||||
|
lex_print_position(lex, &lex->eb);
|
||||||
|
|
||||||
lex->tok.type = TOK_ERROR;
|
lex->tok.type = TOK_ERROR;
|
||||||
return;
|
return;
|
||||||
@ -130,19 +115,34 @@ struct token *lex_token(struct lexer *lex) {
|
|||||||
return &lex->tok;
|
return &lex->tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lex_print_position(const struct lexer *lex) {
|
void lex_print_position(const struct lexer *lex, struct error_buffer *eb) {
|
||||||
int i;
|
size_t pos = lex->prev_p - lex->start;
|
||||||
int pos = lex->prev_p - lex->start;
|
size_t i;
|
||||||
|
size_t input_len = strlen(lex->start);
|
||||||
fprintf(stderr, "At character %d\n", pos);
|
|
||||||
fprintf(stderr, " %s\n", lex->start);
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
for (i = 0; i < pos; ++i)
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
|
|
||||||
fprintf(stderr, "^\n----------------------------------------------------\n");
|
error_printf(eb, "At character %d\n", pos);
|
||||||
|
error_printf(eb, " %s\n", lex->start);
|
||||||
|
error_printf(eb, " ");
|
||||||
|
|
||||||
|
for (i = 0; i < input_len; ++i) {
|
||||||
|
char c = '_';
|
||||||
|
if (i == pos)
|
||||||
|
c = '^';
|
||||||
|
|
||||||
|
error_printf(eb, "%c", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_printf(eb, "\n");
|
||||||
|
/* error_printf(eb, "\n----------------------------------------------------\n"); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum error_code lex_get_error(const struct lexer *lex) {
|
||||||
|
return error_get(&lex->eb);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lex_get_error_text(const struct lexer *lex) {
|
||||||
|
return error_get_text(&lex->eb);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LEX_DEBUG
|
#ifdef LEX_DEBUG
|
||||||
|
|
||||||
|
|||||||
23
lex.h
23
lex.h
@ -1,6 +1,8 @@
|
|||||||
#ifndef LEX_H
|
#ifndef LEX_H
|
||||||
#define LEX_H
|
#define LEX_H
|
||||||
|
|
||||||
|
#include "error_buffer.h"
|
||||||
|
|
||||||
#define LEX_DEBUG
|
#define LEX_DEBUG
|
||||||
|
|
||||||
enum token_type {
|
enum token_type {
|
||||||
@ -43,19 +45,26 @@ struct token {
|
|||||||
} val;
|
} val;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lexer;
|
struct lexer {
|
||||||
|
const char *start;
|
||||||
|
const char *prev_p;
|
||||||
|
const char *p;
|
||||||
|
struct token tok;
|
||||||
|
struct error_buffer eb;
|
||||||
|
};
|
||||||
|
|
||||||
extern struct lexer *lex_create(const char *str);
|
void lex_init(struct lexer *lex, const char *str);
|
||||||
extern void lex_free(struct lexer *lex);
|
|
||||||
|
|
||||||
extern void lex_next(struct lexer *lex);
|
void lex_next(struct lexer *lex);
|
||||||
extern struct token *lex_token(struct lexer *lex);
|
struct token *lex_token(struct lexer *lex);
|
||||||
|
|
||||||
extern void lex_print_position(const struct lexer *lex);
|
void lex_print_position(const struct lexer *lex, struct error_buffer *eb);
|
||||||
|
|
||||||
|
enum error_code lex_get_error(const struct lexer *lex);
|
||||||
|
const char *lex_get_error_text(const struct lexer *lex);
|
||||||
|
|
||||||
#ifdef LEX_DEBUG
|
#ifdef LEX_DEBUG
|
||||||
extern void lex_debug_print_token(const struct token *tok);
|
void lex_debug_print_token(const struct token *tok);
|
||||||
#endif /* LEX_DEBUG */
|
#endif /* LEX_DEBUG */
|
||||||
|
|
||||||
#endif /* LEX_H */
|
#endif /* LEX_H */
|
||||||
48
main.c
48
main.c
@ -6,40 +6,40 @@
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
struct lexer *lex;
|
struct parser parser;
|
||||||
struct expr_node *node;
|
struct expr_node *node;
|
||||||
|
FILE *file;
|
||||||
|
struct graph_range graph;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("Usage: %s <expression>\n", argv[0]);
|
printf("Usage: %s <expression>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lex = lex_create(argv[1]);
|
parser_init(&parser);
|
||||||
|
node = parser_parse(&parser, argv[1]);
|
||||||
|
|
||||||
node = parse_expression(lex);
|
if (!node) {
|
||||||
lex_free(lex);
|
fprintf(stderr, "%s", parser_get_error_text(&parser));
|
||||||
|
return parser_get_error(&parser);
|
||||||
if (node) {
|
|
||||||
FILE *file;
|
|
||||||
struct graph_range graph;
|
|
||||||
|
|
||||||
graph.xmin = -20.0;
|
|
||||||
graph.xmax = 20.0;
|
|
||||||
graph.ymin = -20.0;
|
|
||||||
graph.ymax = 20.0;
|
|
||||||
graph.step = 0.01;
|
|
||||||
|
|
||||||
file = fopen("out.ps", "w");
|
|
||||||
ps_export_graph(file, node, &graph);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
file = fopen("graph.dot", "w");
|
|
||||||
node_debug_print_gv(node, file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
node_free(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graph.xmin = -20.0;
|
||||||
|
graph.xmax = 20.0;
|
||||||
|
graph.ymin = -20.0;
|
||||||
|
graph.ymax = 20.0;
|
||||||
|
graph.step = 0.01;
|
||||||
|
|
||||||
|
file = fopen("out.ps", "w");
|
||||||
|
ps_export_graph(file, node, &graph);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
file = fopen("graph.dot", "w");
|
||||||
|
node_debug_print_gv(node, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
node_free(node);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
244
parser.c
244
parser.c
@ -2,81 +2,101 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
static int token_is(struct lexer *lex, enum token_type type) {
|
static struct token *get_token(struct parser *parser) {
|
||||||
return lex_token(lex)->type == type;
|
return lex_token(&parser->lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int accept(struct lexer *lex, enum token_type type) {
|
static int token_is(struct parser *parser, enum token_type type) {
|
||||||
if (token_is(lex, type)) {
|
return get_token(parser)->type == type;
|
||||||
lex_next(lex);
|
}
|
||||||
|
|
||||||
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double token_num(struct lexer *lex) {
|
static void error_bad_alloc(struct parser *parser) {
|
||||||
return lex_token(lex)->val.num;
|
error_set(&parser->eb, ERR_BAD_ALLOC);
|
||||||
|
error_printf(&parser->eb, "Out of memory\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum math_fn token_fn(struct lexer *lex) {
|
static void error_expected_one_of(struct parser *parser, const int expected[]) {
|
||||||
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[] = {
|
static const char* token_name[] = {
|
||||||
"end of expression",
|
"end of expression",
|
||||||
"lexer error",
|
"lexer error",
|
||||||
"constant",
|
"constant",
|
||||||
"+",
|
"+",
|
||||||
"-",
|
"-",
|
||||||
"*",
|
"*",
|
||||||
"/",
|
"/",
|
||||||
"^",
|
"^",
|
||||||
"x",
|
"x",
|
||||||
"function name",
|
"function name",
|
||||||
"(",
|
"(",
|
||||||
")"
|
")"
|
||||||
};
|
};
|
||||||
|
|
||||||
int separate = 0;
|
size_t i;
|
||||||
|
|
||||||
fprintf(stderr, "Syntax error - expected ");
|
enum token_type got = get_token(parser)->type;
|
||||||
|
|
||||||
for (; *expected >= 0; ++expected) {
|
if (got == TOK_ERROR) {
|
||||||
if (separate)
|
error_set(&parser->eb, lex_get_error(&parser->lexer));
|
||||||
fprintf(stderr, ", ");
|
error_printf(&parser->eb, "Lexer error - %s", lex_get_error_text(&parser->lexer));
|
||||||
else
|
return;
|
||||||
separate = 1;
|
|
||||||
|
|
||||||
fprintf(stderr, "'%s'", token_name[*expected]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, " - but got '%s'\n", token_name[got]);
|
error_set(&parser->eb, ERR_INVALID_FUNCTION);
|
||||||
|
error_printf(&parser->eb, "Syntax error - expected ");
|
||||||
|
|
||||||
lex_print_position(lex);
|
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 lexer* lex, enum token_type expected, enum token_type got) {
|
static void error_expected_single(struct parser *parser, enum token_type expected) {
|
||||||
static int expected_arr[] = { -1, -1 };
|
static int expected_arr[] = { -1, -1 };
|
||||||
expected_arr[0] = expected;
|
expected_arr[0] = expected;
|
||||||
error_expected_one_of(lex, expected_arr, got);
|
error_expected_one_of(parser, expected_arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct expr_node* parse_subexpression(struct lexer* lex);
|
static struct expr_node* parse_subexpression(struct parser *parser);
|
||||||
|
|
||||||
static struct expr_node* parse_bracketed(struct lexer* lex) {
|
static struct expr_node* parse_bracketed(struct parser *parser) {
|
||||||
struct expr_node* node;
|
struct expr_node* node;
|
||||||
|
|
||||||
if (!accept(lex, TOK_LEFT_PAREN)) {
|
if (!accept_token(parser, TOK_LEFT_PAREN)) {
|
||||||
error_expected_single(lex, TOK_LEFT_PAREN, lex_token(lex)->type);
|
error_expected_single(parser, TOK_LEFT_PAREN);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(node = parse_subexpression(lex)))
|
if (!(node = parse_subexpression(parser)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!accept(lex, TOK_RIGHT_PAREN)) {
|
if (!accept_token(parser, TOK_RIGHT_PAREN)) {
|
||||||
error_expected_single(lex, TOK_RIGHT_PAREN, lex_token(lex)->type);
|
error_expected_single(parser, TOK_RIGHT_PAREN);
|
||||||
node_free(node);
|
node_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -84,60 +104,72 @@ static struct expr_node* parse_bracketed(struct lexer* lex) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct expr_node *parse_base(struct lexer *lex) {
|
static struct expr_node *parse_base(struct parser *parser) {
|
||||||
struct expr_node *node, *inner;
|
struct expr_node *node, *inner;
|
||||||
|
|
||||||
if (token_is(lex, TOK_NUMBER)) {
|
if (token_is(parser, TOK_NUMBER)) {
|
||||||
double val = token_num(lex);
|
double val = token_num(parser);
|
||||||
lex_next(lex);
|
next_token(parser);
|
||||||
return node_create_const(val);
|
if (!(node = node_create_const(val))) {
|
||||||
}
|
error_bad_alloc(parser);
|
||||||
|
|
||||||
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 NULL;
|
||||||
|
|
||||||
if (!(node = node_create_fn(fn, inner))) {
|
|
||||||
node_free(inner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token_is(lex, TOK_LEFT_PAREN)) {
|
if (accept_token(parser, TOK_X)) {
|
||||||
return parse_bracketed(lex);
|
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 };
|
static const int expected[] = { TOK_NUMBER, TOK_X, TOK_FUNCTION, TOK_LEFT_PAREN, -1 };
|
||||||
error_expected_one_of(lex, expected, lex_token(lex)->type);
|
error_expected_one_of(parser, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct expr_node* parse_unary(struct lexer* lex);
|
static struct expr_node *parse_unary(struct parser *parser);
|
||||||
|
|
||||||
static struct expr_node* parse_factor(struct lexer* lex) {
|
static struct expr_node *parse_factor(struct parser *parser) {
|
||||||
struct expr_node* node, * new_node, * inner;
|
struct expr_node* node, * new_node, * inner;
|
||||||
|
|
||||||
if (!(node = parse_base(lex)))
|
if (!(node = parse_base(parser)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (accept(lex, TOK_POWER)) {
|
if (accept_token(parser, TOK_POWER)) {
|
||||||
if (!(inner = parse_unary(lex))) {
|
if (!(inner = parse_unary(parser))) {
|
||||||
node_free(node);
|
node_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_node = node_create_pow(node, inner))) {
|
if (!(new_node = node_create_pow(node, inner))) {
|
||||||
|
error_bad_alloc(parser);
|
||||||
node_free(node);
|
node_free(node);
|
||||||
node_free(inner);
|
node_free(inner);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -149,14 +181,15 @@ static struct expr_node* parse_factor(struct lexer* lex) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct expr_node* parse_unary(struct lexer *lex) {
|
static struct expr_node* parse_unary(struct parser *parser) {
|
||||||
if (accept(lex, TOK_MINUS)) {
|
if (accept_token(parser, TOK_MINUS)) {
|
||||||
struct expr_node *node, *inner;
|
struct expr_node *node, *inner;
|
||||||
|
|
||||||
if (!(inner = parse_factor(lex)))
|
if (!(inner = parse_factor(parser)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(node = node_create_neg(inner))) {
|
if (!(node = node_create_neg(inner))) {
|
||||||
|
error_bad_alloc(parser);
|
||||||
node_free(inner);
|
node_free(inner);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -164,32 +197,33 @@ static struct expr_node* parse_unary(struct lexer *lex) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
accept(lex, TOK_PLUS);
|
accept_token(parser, TOK_PLUS);
|
||||||
return parse_factor(lex);
|
return parse_factor(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct expr_node *parse_term(struct lexer *lex) {
|
static struct expr_node *parse_term(struct parser *parser) {
|
||||||
struct expr_node *node, *new_node, *inner;
|
struct expr_node *node, *new_node, *inner;
|
||||||
|
|
||||||
if (!(node = parse_unary(lex)))
|
if (!(node = parse_unary(parser)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right);
|
struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right);
|
||||||
|
|
||||||
if (accept(lex, TOK_MULTIPLY))
|
if (accept_token(parser, TOK_MULTIPLY))
|
||||||
create_node = node_create_mult;
|
create_node = node_create_mult;
|
||||||
else if (accept(lex, TOK_DIVIDE))
|
else if (accept_token(parser, TOK_DIVIDE))
|
||||||
create_node = node_create_div;
|
create_node = node_create_div;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(inner = parse_unary(lex))) {
|
if (!(inner = parse_unary(parser))) {
|
||||||
node_free(node);
|
node_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_node = create_node(node, inner))) {
|
if (!(new_node = create_node(node, inner))) {
|
||||||
|
error_bad_alloc(parser);
|
||||||
node_free(node);
|
node_free(node);
|
||||||
node_free(inner);
|
node_free(inner);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -201,47 +235,29 @@ static struct expr_node *parse_term(struct lexer *lex) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct expr_node *parse_subexpression(struct lexer *lex) {
|
static struct expr_node *parse_subexpression(struct parser *parser) {
|
||||||
struct expr_node *node, *new_node, *inner;
|
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))) {
|
if (!(node = parse_term(parser)))
|
||||||
node_free(term);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
accept(lex, TOK_PLUS);
|
|
||||||
|
|
||||||
if (!(node = parse_term(lex)))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!(node = parse_term(lex)))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right);
|
struct expr_node *(*create_node)(struct expr_node *left, struct expr_node *right);
|
||||||
|
|
||||||
if (accept(lex, TOK_PLUS))
|
if (accept_token(parser, TOK_PLUS))
|
||||||
create_node = node_create_add;
|
create_node = node_create_add;
|
||||||
else if (accept(lex, TOK_MINUS))
|
else if (accept_token(parser, TOK_MINUS))
|
||||||
create_node = node_create_sub;
|
create_node = node_create_sub;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(inner = parse_term(lex))) {
|
if (!(inner = parse_term(parser))) {
|
||||||
node_free(node);
|
node_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_node = create_node(node, inner))) {
|
if (!(new_node = create_node(node, inner))) {
|
||||||
|
error_bad_alloc(parser);
|
||||||
node_free(node);
|
node_free(node);
|
||||||
node_free(inner);
|
node_free(inner);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -253,17 +269,35 @@ struct expr_node *parse_subexpression(struct lexer *lex) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct expr_node *parse_expression(struct lexer *lex) {
|
static struct expr_node *parse_expression(struct parser *parser) {
|
||||||
struct expr_node *node;
|
struct expr_node *node;
|
||||||
|
|
||||||
if (!(node = parse_subexpression(lex)))
|
if (!(node = parse_subexpression(parser)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!token_is(lex, TOK_EOF)) {
|
if (!token_is(parser, TOK_EOF)) {
|
||||||
error_expected_single(lex, TOK_EOF, lex_token(lex)->type);
|
error_expected_single(parser, TOK_EOF);
|
||||||
node_free(node);
|
node_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
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);
|
||||||
}
|
}
|
||||||
12
parser.h
12
parser.h
@ -2,7 +2,17 @@
|
|||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
|
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "lex.h"
|
||||||
|
|
||||||
extern struct expr_node *parse_expression(struct lexer *lex);
|
struct parser {
|
||||||
|
struct lexer lexer;
|
||||||
|
struct error_buffer eb;
|
||||||
|
};
|
||||||
|
|
||||||
|
void parser_init(struct parser *parser);
|
||||||
|
struct expr_node *parser_parse(struct parser *parser, const char *str);
|
||||||
|
|
||||||
|
enum error_code parser_get_error(const struct parser *parser);
|
||||||
|
const char *parser_get_error_text(const struct parser *parser);
|
||||||
|
|
||||||
#endif /* PARSER_H */
|
#endif /* PARSER_H */
|
||||||
Loading…
x
Reference in New Issue
Block a user