Restructure a bit
This commit is contained in:
111
src/parser.c
111
src/parser.c
@@ -33,6 +33,8 @@ expr
|
||||
| INT OPERATOR FLOAT {conv($1); $$ = binary_op_float($1, $3, $2);}
|
||||
| FLOAT OPERATOR INT {conv($2); $$ = binary_op_float($1, $3, $2);}
|
||||
| FLOAT OPERATOR FLOAT {$$ = binary_op_float($1, $3, $2);};
|
||||
| INT
|
||||
| FLOAT
|
||||
============================= */
|
||||
|
||||
enum value_type {
|
||||
@@ -48,34 +50,48 @@ static const char* value_type_str[VALUE_TYPE_COUNT] = {
|
||||
[VALUE_FLOATING] = "VALUE_FLOATING",
|
||||
};
|
||||
|
||||
static const int operator_precedence[256] = {
|
||||
['+'] = 0,
|
||||
['-'] = 0,
|
||||
['*'] = 10,
|
||||
['/'] = 10,
|
||||
};
|
||||
|
||||
typedef struct parser {
|
||||
Token* cur;
|
||||
Token* next;
|
||||
Mfile* m;
|
||||
} Parser;
|
||||
|
||||
bool parser_advance(Error* err, Parser* p)
|
||||
{
|
||||
p->cur = p->next;
|
||||
mfile_skip(p->m, isspace);
|
||||
p->next = token_read(err, p->m);
|
||||
if (!error_empty(err)) {
|
||||
error_push(err, "%s failed", __func__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct value {
|
||||
const char* debug_name;
|
||||
enum value_type type;
|
||||
union {
|
||||
int64_t i64;
|
||||
char op[3];
|
||||
double f64;
|
||||
char op[3];
|
||||
};
|
||||
} Value;
|
||||
|
||||
typedef struct symbol_table_entry {
|
||||
const char* debug_name;
|
||||
int id;
|
||||
Value* val;
|
||||
struct symbol_table_entry* next;
|
||||
} Symbol_table_entry;
|
||||
|
||||
typedef struct symbol_table {
|
||||
Symbol_table_entry* syms;
|
||||
} Symbol_table;
|
||||
|
||||
static Value* parse_operator(Error* err, Token* t)
|
||||
{
|
||||
if (t->type != TOKEN_OPERATOR) {
|
||||
error_push(err, "%s: unexpected token type: %s", __func__, token_type_str[t->type]);
|
||||
return NULL;
|
||||
}
|
||||
Value* v = malloc(sizeof *v);
|
||||
Value* v = calloc(1, sizeof *v);
|
||||
if (!v) {
|
||||
error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno));
|
||||
return NULL;
|
||||
@@ -91,7 +107,7 @@ static Value* parse_int(Error* err, Token* t)
|
||||
error_push(err, "%s: unexpected token type: %s", __func__, token_type_str[t->type]);
|
||||
return NULL;
|
||||
}
|
||||
Value* v = malloc(sizeof *v);
|
||||
Value* v = calloc(1, sizeof *v);
|
||||
if (!v) {
|
||||
error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno));
|
||||
return NULL;
|
||||
@@ -110,12 +126,12 @@ static Value* parse_int(Error* err, Token* t)
|
||||
static Value* parse_floating(Error* err, Token* t)
|
||||
{
|
||||
if (t->type != TOKEN_FLOATING) {
|
||||
error_push(err, "%s: unexpected token type: %s", __func__, token_type_str[t->type]);
|
||||
error_push(err, "(%s) unexpected token type: %s", __func__, token_type_str[t->type]);
|
||||
return NULL;
|
||||
}
|
||||
Value* v = malloc(sizeof *v);
|
||||
Value* v = calloc(1, sizeof *v);
|
||||
if (!v) {
|
||||
error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno));
|
||||
error_push(err, "(%s) failed to allocate value: %s", __func__, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
v->type = VALUE_FLOATING;
|
||||
@@ -123,7 +139,7 @@ static Value* parse_floating(Error* err, Token* t)
|
||||
errno = 0;
|
||||
v->f64= strtod(t->start, NULL);
|
||||
if (errno != 0) {
|
||||
error_push(err, "%s: failed to parse float: %s", __func__, strerror(errno));
|
||||
error_push(err, "(%s) failed to parse float: %s", __func__, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
return v;
|
||||
@@ -175,7 +191,7 @@ static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* result = malloc(sizeof *result);
|
||||
Value* result = calloc(1, sizeof *result);
|
||||
if (!result) {
|
||||
error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno));
|
||||
return NULL;
|
||||
@@ -222,32 +238,44 @@ static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op)
|
||||
return result;
|
||||
}
|
||||
|
||||
static Value* parser_handle_binary_expr(Error* err, Token* peek, Mfile* m)
|
||||
static Value* parse_expr(Error* err, Parser* p)
|
||||
{
|
||||
Value* lval = parse_number(err, peek);
|
||||
Value* lval = parse_number(err, p->cur);
|
||||
if (!error_empty(err) || !lval) {
|
||||
goto generic_error;
|
||||
}
|
||||
|
||||
Token* op_tok = token_read(err, m);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
} else if (op_tok->type != TOKEN_OPERATOR) {
|
||||
} else if (p->next->type != TOKEN_OPERATOR) {
|
||||
parser_advance(err, p);
|
||||
if (!error_empty(err)) {
|
||||
goto syntax_error;
|
||||
}
|
||||
return lval;
|
||||
}
|
||||
|
||||
Value* op = parse_operator(err, op_tok);
|
||||
Value* op = parse_operator(err, p->next);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
}
|
||||
parser_advance(err, p);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
}
|
||||
parser_advance(err, p);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
}
|
||||
|
||||
Token* rval_tok = token_read(err, m);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
} else if (rval_tok->type != TOKEN_INTEGER && rval_tok->type != TOKEN_FLOATING) {
|
||||
} else if (p->cur->type != TOKEN_INTEGER
|
||||
&& p->cur->type != TOKEN_FLOATING)
|
||||
{
|
||||
goto syntax_error;
|
||||
}
|
||||
Value* rval = parse_number(err, rval_tok);
|
||||
Value* rval = parse_expr(err, p);
|
||||
if (!error_empty(err)) {
|
||||
goto generic_error;
|
||||
}
|
||||
@@ -264,28 +292,27 @@ generic_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Value* parser_next(Error* err, Mfile* m)
|
||||
static Value* parser_next(Error* err, Parser* p)
|
||||
{
|
||||
mfile_skip(m, isspace);
|
||||
Token* t = token_read(err, m);
|
||||
if (t->type == EOF) {
|
||||
return NULL;
|
||||
} else if (!error_empty(err)) {
|
||||
if (p->cur->type == EOF || !error_empty(err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* result;
|
||||
switch (t->type) {
|
||||
switch (p->cur->type) {
|
||||
case TOKEN_INTEGER:
|
||||
case TOKEN_FLOATING:
|
||||
{
|
||||
result = parser_handle_binary_expr(err, t, m);
|
||||
result = parse_expr(err, p);
|
||||
if (!error_empty(err)) {
|
||||
goto syntax_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: syntax_error: {
|
||||
error_push(err, "(%s) syntax error: unexpected token %s", __func__, token_type_str[t->type]);
|
||||
default:
|
||||
syntax_error:
|
||||
{
|
||||
error_push(err, "(%s) syntax error: unexpected token %s", __func__, token_type_str[p->cur->type]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -317,8 +344,16 @@ int main(int argc, char** argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Parser p = {
|
||||
.cur = NULL,
|
||||
.next = NULL,
|
||||
.m = m,
|
||||
};
|
||||
parser_advance(&err, &p);
|
||||
parser_advance(&err, &p);
|
||||
|
||||
while (!mfile_eof(m)) {
|
||||
parser_next(&err, m);
|
||||
parser_next(&err, &p);
|
||||
if (!error_empty(&err)) {
|
||||
error_print(&err);
|
||||
return EXIT_FAILURE;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
1+2
|
||||
1 + 4
|
||||
1 + 4 + 3
|
||||
5 / 2
|
||||
1.3 * 2
|
||||
|
||||
Reference in New Issue
Block a user