Restructure a bit

This commit is contained in:
2024-01-07 14:54:46 +01:00
parent 61ee6d10d9
commit 33d07bea37
2 changed files with 260 additions and 225 deletions

View File

@@ -25,271 +25,298 @@ statement:
| statement; | statement;
statement statement
: expr : expr
| assignment; | assignment;
assignment assignment
: IDENTIFIER TYPE ASSIGNMENT expr : IDENTIFIER TYPE ASSIGNMENT expr
expr expr
: INT OPERATOR INT {$$ = binary_op_int($1, $3, $2);} : INT OPERATOR INT {$$ = binary_op_int($1, $3, $2);}
| INT OPERATOR FLOAT {conv($1); $$ = binary_op_float($1, $3, $2);} | INT OPERATOR FLOAT {conv($1); $$ = binary_op_float($1, $3, $2);}
| FLOAT OPERATOR INT {conv($2); $$ = 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);}; | FLOAT OPERATOR FLOAT {$$ = binary_op_float($1, $3, $2);};
| INT
| FLOAT
============================= */ ============================= */
enum value_type { enum value_type {
VALUE_INTEGER, VALUE_INTEGER,
VALUE_OPERATOR, VALUE_OPERATOR,
VALUE_FLOATING, VALUE_FLOATING,
VALUE_TYPE_COUNT, VALUE_TYPE_COUNT,
}; };
static const char* value_type_str[VALUE_TYPE_COUNT] = { static const char* value_type_str[VALUE_TYPE_COUNT] = {
[VALUE_INTEGER] = "VALUE_INTEGER", [VALUE_INTEGER] = "VALUE_INTEGER",
[VALUE_OPERATOR] = "VALUE_OPERATOR", [VALUE_OPERATOR] = "VALUE_OPERATOR",
[VALUE_FLOATING] = "VALUE_FLOATING", [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 { typedef struct value {
const char* debug_name;
enum value_type type;
union {
int64_t i64;
char op[3];
double f64;
};
} Value;
typedef struct symbol_table_entry {
const char* debug_name; const char* debug_name;
int id; enum value_type type;
Value* val; union {
struct symbol_table_entry* next; int64_t i64;
} Symbol_table_entry; double f64;
char op[3];
typedef struct symbol_table { };
Symbol_table_entry* syms; } Value;
} Symbol_table;
static Value* parse_operator(Error* err, Token* t) static Value* parse_operator(Error* err, Token* t)
{ {
if (t->type != TOKEN_OPERATOR) { if (t->type != TOKEN_OPERATOR) {
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; return NULL;
} }
Value* v = malloc(sizeof *v); Value* v = calloc(1, sizeof *v);
if (!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; return NULL;
} }
v->type = VALUE_OPERATOR; v->type = VALUE_OPERATOR;
strncpy(v->op, t->start, MIN(t->end - t->start, sizeof(v->op))); strncpy(v->op, t->start, MIN(t->end - t->start, sizeof(v->op)));
return v; return v;
} }
static Value* parse_int(Error* err, Token* t) static Value* parse_int(Error* err, Token* t)
{ {
if (t->type != TOKEN_INTEGER) { if (t->type != TOKEN_INTEGER) {
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; return NULL;
} }
Value* v = malloc(sizeof *v); Value* v = calloc(1, sizeof *v);
if (!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; return NULL;
} }
v->type = VALUE_INTEGER; v->type = VALUE_INTEGER;
assert(errno == 0); assert(errno == 0);
errno = 0; errno = 0;
v->i64= strtol(t->start, NULL, 10); v->i64= strtol(t->start, NULL, 10);
if (errno != 0) { if (errno != 0) {
error_push(err, "%s: failed to parse int: %s", __func__, strerror(errno)); error_push(err, "%s: failed to parse int: %s", __func__, strerror(errno));
return NULL; return NULL;
} }
return v; return v;
} }
static Value* parse_floating(Error* err, Token* t) static Value* parse_floating(Error* err, Token* t)
{ {
if (t->type != TOKEN_FLOATING) { 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; return NULL;
} }
Value* v = malloc(sizeof *v); Value* v = calloc(1, sizeof *v);
if (!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; return NULL;
} }
v->type = VALUE_FLOATING; v->type = VALUE_FLOATING;
assert(errno == 0); assert(errno == 0);
errno = 0; errno = 0;
v->f64= strtod(t->start, NULL); v->f64= strtod(t->start, NULL);
if (errno != 0) { 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 NULL;
} }
return v; return v;
} }
static Value* parse_number(Error* err, Token* t) static Value* parse_number(Error* err, Token* t)
{ {
switch (t->type) { switch (t->type) {
case TOKEN_FLOATING: case TOKEN_FLOATING:
return parse_floating(err, t); return parse_floating(err, t);
case TOKEN_INTEGER: case TOKEN_INTEGER:
return parse_int(err, t); return parse_int(err, t);
default: default:
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; return NULL;
} }
} }
static void conv_int_to_float(Error* err, Value* val) static void conv_int_to_float(Error* err, Value* val)
{ {
if (val->type != VALUE_INTEGER) { if (val->type != VALUE_INTEGER) {
error_push(err, "(%s) conversion from %s to float not implemented", __func__, value_type_str[val->type]); error_push(err, "(%s) conversion from %s to float not implemented", __func__, value_type_str[val->type]);
return; return;
} }
fprintf(stderr, "converting %ld to %lf", val->i64, (double)val->i64); fprintf(stderr, "converting %ld to %lf", val->i64, (double)val->i64);
val->f64 = (double)val->i64; val->f64 = (double)val->i64;
val->type = VALUE_FLOATING; val->type = VALUE_FLOATING;
} }
static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op) static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op)
{ {
if ((lval->type != VALUE_INTEGER && lval->type != VALUE_FLOATING) if ((lval->type != VALUE_INTEGER && lval->type != VALUE_FLOATING)
|| (rval->type != VALUE_INTEGER && rval->type != VALUE_FLOATING) || (rval->type != VALUE_INTEGER && rval->type != VALUE_FLOATING)
|| op->type != VALUE_OPERATOR) || op->type != VALUE_OPERATOR)
{ {
error_push(err, "%s: unexpected token types: %s %s %s", error_push(err, "%s: unexpected token types: %s %s %s",
__func__, value_type_str[lval->type], __func__, value_type_str[lval->type],
value_type_str[rval->type], value_type_str[op->type]); value_type_str[rval->type], value_type_str[op->type]);
return NULL; return NULL;
} }
if (lval->type == VALUE_FLOATING && rval->type == VALUE_INTEGER) { if (lval->type == VALUE_FLOATING && rval->type == VALUE_INTEGER) {
conv_int_to_float(err, rval); conv_int_to_float(err, rval);
} else if (lval->type == VALUE_INTEGER && rval->type == VALUE_FLOATING) { } else if (lval->type == VALUE_INTEGER && rval->type == VALUE_FLOATING) {
conv_int_to_float(err, lval); conv_int_to_float(err, lval);
} }
if (!error_empty(err)) { if (!error_empty(err)) {
error_push(err, "binary expression failed"); error_push(err, "binary expression failed");
return NULL; return NULL;
} }
Value* result = malloc(sizeof *result); Value* result = calloc(1, sizeof *result);
if (!result) { if (!result) {
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; return NULL;
} }
fprintf(stderr, "\ndoing op: %s %c %s", value_type_str[lval->type], op->op[0], value_type_str[rval->type]); fprintf(stderr, "\ndoing op: %s %c %s", value_type_str[lval->type], op->op[0], value_type_str[rval->type]);
if (rval->type == VALUE_INTEGER && lval->type == VALUE_INTEGER) { if (rval->type == VALUE_INTEGER && lval->type == VALUE_INTEGER) {
result->type = VALUE_INTEGER; result->type = VALUE_INTEGER;
switch (op->op[0]) { switch (op->op[0]) {
case '+': case '+':
result->i64 = lval->i64 + rval->i64; result->i64 = lval->i64 + rval->i64;
break; break;
case '*': case '*':
result->i64 = lval->i64 * rval->i64; result->i64 = lval->i64 * rval->i64;
break; break;
case '-': case '-':
result->i64 = lval->i64 - rval->i64; result->i64 = lval->i64 - rval->i64;
break; break;
case '/': case '/':
result->i64 = lval->i64 / rval->i64; result->i64 = lval->i64 / rval->i64;
break; break;
} }
printf("\nCALCULATED EXPRESSION %ld %c %ld = %ld\n", lval->i64, printf("\nCALCULATED EXPRESSION %ld %c %ld = %ld\n", lval->i64,
op->op[0], rval->i64, result->i64); op->op[0], rval->i64, result->i64);
} else if (rval->type == VALUE_FLOATING && lval->type == VALUE_FLOATING) { } else if (rval->type == VALUE_FLOATING && lval->type == VALUE_FLOATING) {
result->type = VALUE_FLOATING; result->type = VALUE_FLOATING;
switch (op->op[0]) { switch (op->op[0]) {
case '+': case '+':
result->f64 = lval->f64 + rval->f64; result->f64 = lval->f64 + rval->f64;
break; break;
case '*': case '*':
result->f64 = lval->f64 * rval->f64; result->f64 = lval->f64 * rval->f64;
break; break;
case '-': case '-':
result->f64 = lval->f64 - rval->f64; result->f64 = lval->f64 - rval->f64;
break; break;
case '/': case '/':
result->f64 = lval->f64 / rval->f64; result->f64 = lval->f64 / rval->f64;
break; break;
} }
printf("\nCALCULATED EXPRESSION %lf %c %lf = %lf\n", lval->f64, printf("\nCALCULATED EXPRESSION %lf %c %lf = %lf\n", lval->f64,
op->op[0], rval->f64, result->f64); op->op[0], rval->f64, result->f64);
} }
return result; 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) { if (!error_empty(err) || !lval) {
goto generic_error; goto generic_error;
} }
Token* op_tok = token_read(err, m); if (!error_empty(err)) {
if (!error_empty(err)) { goto generic_error;
goto generic_error; } else if (p->next->type != TOKEN_OPERATOR) {
} else if (op_tok->type != TOKEN_OPERATOR) { parser_advance(err, p);
goto syntax_error; 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)) { if (!error_empty(err)) {
goto generic_error; 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)) {
if (!error_empty(err)) { goto generic_error;
goto generic_error; } else if (p->cur->type != TOKEN_INTEGER
} else if (rval_tok->type != TOKEN_INTEGER && rval_tok->type != TOKEN_FLOATING) { && p->cur->type != TOKEN_FLOATING)
goto syntax_error; {
} goto syntax_error;
Value* rval = parse_number(err, rval_tok); }
if (!error_empty(err)) { Value* rval = parse_expr(err, p);
goto generic_error; if (!error_empty(err)) {
} goto generic_error;
}
Value* result = parse_binary_expr(err, lval, rval, op); Value* result = parse_binary_expr(err, lval, rval, op);
if (!error_empty(err)) { if (!error_empty(err)) {
goto generic_error; goto generic_error;
} }
return result; return result;
syntax_error: syntax_error:
error_push(err, "%s: syntax error, expected binary expression", __func__); error_push(err, "%s: syntax error, expected binary expression", __func__);
generic_error: generic_error:
return NULL; return NULL;
} }
static Value* parser_next(Error* err, Mfile* m) static Value* parser_next(Error* err, Parser* p)
{ {
mfile_skip(m, isspace); if (p->cur->type == EOF || !error_empty(err)) {
Token* t = token_read(err, m); return NULL;
if (t->type == EOF) { }
return NULL;
} else if (!error_empty(err)) { Value* result;
return NULL; switch (p->cur->type) {
} case TOKEN_INTEGER:
Value* result; case TOKEN_FLOATING:
switch (t->type) { {
case TOKEN_INTEGER: result = parse_expr(err, p);
case TOKEN_FLOATING: if (!error_empty(err)) {
{ goto syntax_error;
result = parser_handle_binary_expr(err, t, m); }
if (!error_empty(err)) { break;
goto syntax_error; }
} default:
break; syntax_error:
} {
default: syntax_error: { error_push(err, "(%s) syntax error: unexpected token %s", __func__, token_type_str[p->cur->type]);
error_push(err, "(%s) syntax error: unexpected token %s", __func__, token_type_str[t->type]); return NULL;
return NULL; }
} }
} return result;
return result;
} }
/* ========================================================================= */ /* ========================================================================= */
@@ -298,15 +325,15 @@ int main(int argc, char** argv)
{ {
int status = EXIT_SUCCESS; int status = EXIT_SUCCESS;
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]); fprintf(stderr, "usage: %s <file>\n", argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// create a protected page for debugging purposes // create a protected page for debugging purposes
size_t pagesize = sysconf(_SC_PAGESIZE); size_t pagesize = sysconf(_SC_PAGESIZE);
void* protected_page = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); void* protected_page = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
mfile_overflow_slope = protected_page + 0; mfile_overflow_slope = protected_page + 0;
mprotect(protected_page, pagesize, PROT_NONE); mprotect(protected_page, pagesize, PROT_NONE);
Error err = ERROR_INIT; Error err = ERROR_INIT;
@@ -317,13 +344,21 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
while (!mfile_eof(m)) { Parser p = {
parser_next(&err, m); .cur = NULL,
if (!error_empty(&err)) { .next = NULL,
error_print(&err); .m = m,
return EXIT_FAILURE; };
} parser_advance(&err, &p);
} parser_advance(&err, &p);
while (!mfile_eof(m)) {
parser_next(&err, &p);
if (!error_empty(&err)) {
error_print(&err);
return EXIT_FAILURE;
}
}
mfile_close(&err, m); mfile_close(&err, m);

View File

@@ -1,4 +1,4 @@
1+2 1+2
1 + 4 1 + 4 + 3
5 / 2 5 / 2
1.3 * 2 1.3 * 2