diff --git a/src/parser.c b/src/parser.c index 4ed462e..bd4458e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -24,32 +24,37 @@ statement: : statements statement | statement; statement - | expr + : expr + | assignment; +assignment + : IDENTIFIER TYPE ASSIGNMENT expr expr : INT OPERATOR INT {$$ = binary_op_int($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 FLOAT {$$ = binary_op_float($1, $3, $2);} - ; + | FLOAT OPERATOR FLOAT {$$ = binary_op_float($1, $3, $2);}; ============================= */ enum value_type { VALUE_INTEGER, VALUE_OPERATOR, + VALUE_FLOATING, 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_FLOATING] = "VALUE_FLOATING", }; typedef struct value { const char* debug_name; enum value_type type; union { - int64_t i; + int64_t i64; char op[3]; + double f64; }; } Value; @@ -94,7 +99,7 @@ static Value* parse_int(Error* err, Token* t) v->type = VALUE_INTEGER; assert(errno == 0); errno = 0; - v->i = strtol(t->start, NULL, 10); + v->i64= strtol(t->start, NULL, 10); if (errno != 0) { error_push(err, "%s: failed to parse int: %s", __func__, strerror(errno)); return NULL; @@ -102,11 +107,57 @@ static Value* parse_int(Error* err, Token* t) return v; } +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]); + return NULL; + } + Value* v = malloc(sizeof *v); + if (!v) { + error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno)); + return NULL; + } + v->type = VALUE_FLOATING; + assert(errno == 0); + errno = 0; + v->f64= strtod(t->start, NULL); + if (errno != 0) { + error_push(err, "%s: failed to parse float: %s", __func__, strerror(errno)); + return NULL; + } + return v; +} + +static Value* parse_number(Error* err, Token* t) +{ + switch (t->type) { + case TOKEN_FLOATING: + return parse_floating(err, t); + case TOKEN_INTEGER: + return parse_int(err, t); + default: + error_push(err, "(%s) unexpected token type %s", __func__, token_type_str[t->type]); + return NULL; + } +} + +static void conv_int_to_float(Error* err, Value* val) +{ + if (val->type != VALUE_INTEGER) { + error_push(err, "(%s) conversion from %s to float not implemented", __func__, value_type_str[val->type]); + return; + } + fprintf(stderr, "converting %ld to %lf", val->i64, (double)val->i64); + val->f64 = (double)val->i64; + val->type = VALUE_FLOATING; +} + static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op) { - if (lval->type != VALUE_INTEGER - || rval->type != VALUE_INTEGER - || op->type != VALUE_OPERATOR) + if ((lval->type != VALUE_INTEGER && lval->type != VALUE_FLOATING) + || (rval->type != VALUE_INTEGER && rval->type != VALUE_FLOATING) + || op->type != VALUE_OPERATOR) { error_push(err, "%s: unexpected token types: %s %s %s", __func__, value_type_str[lval->type], @@ -114,70 +165,103 @@ static Value* parse_binary_expr(Error* err, Value* lval, Value* rval, Value* op) return NULL; } + if (lval->type == VALUE_FLOATING && rval->type == VALUE_INTEGER) { + conv_int_to_float(err, rval); + } else if (lval->type == VALUE_INTEGER && rval->type == VALUE_FLOATING) { + conv_int_to_float(err, lval); + } + if (!error_empty(err)) { + error_push(err, "binary expression failed"); + return NULL; + } + Value* result = malloc(sizeof *result); if (!result) { error_push(err, "%s: failed to allocate value: %s", __func__, strerror(errno)); return NULL; } - result->type = VALUE_INTEGER; - switch (op->op[0]) { - case '+': - result->i = lval->i + rval->i; - break; - case '*': - result->i = lval->i * rval->i; - break; - case '-': - result->i = lval->i - rval->i; - break; - case '/': - result->i = lval->i / rval->i; - break; + + 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) { + result->type = VALUE_INTEGER; + switch (op->op[0]) { + case '+': + result->i64 = lval->i64 + rval->i64; + break; + case '*': + result->i64 = lval->i64 * rval->i64; + break; + case '-': + result->i64 = lval->i64 - rval->i64; + break; + case '/': + result->i64 = lval->i64 / rval->i64; + break; + } + printf("\nCALCULATED EXPRESSION %ld %c %ld = %ld\n", lval->i64, + op->op[0], rval->i64, result->i64); + } else if (rval->type == VALUE_FLOATING && lval->type == VALUE_FLOATING) { + result->type = VALUE_FLOATING; + switch (op->op[0]) { + case '+': + result->f64 = lval->f64 + rval->f64; + break; + case '*': + result->f64 = lval->f64 * rval->f64; + break; + case '-': + result->f64 = lval->f64 - rval->f64; + break; + case '/': + result->f64 = lval->f64 / rval->f64; + break; + } + printf("\nCALCULATED EXPRESSION %lf %c %lf = %lf\n", lval->f64, + op->op[0], rval->f64, result->f64); } - printf("\nCALCULATED EXPRESSION %ld %c %ld = %ld\n", lval->i, op->op[0], rval->i, result->i); return result; } static Value* parser_handle_binary_expr(Error* err, Token* peek, Mfile* m) { - Value* lval = parse_int(err, peek); - if (!error_empty(err) || !lval) { - goto generic_error; - } + Value* lval = parse_number(err, peek); + 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) { - goto syntax_error; - } + Token* op_tok = token_read(err, m); + if (!error_empty(err)) { + goto generic_error; + } else if (op_tok->type != TOKEN_OPERATOR) { + goto syntax_error; + } - Value* op = parse_operator(err, op_tok); - if (!error_empty(err)) { - goto generic_error; - } + Value* op = parse_operator(err, op_tok); + 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) { - goto syntax_error; - } - Value* rval = parse_int(err, rval_tok); - 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) { + goto syntax_error; + } + Value* rval = parse_number(err, rval_tok); + if (!error_empty(err)) { + goto generic_error; + } - Value* result = parse_binary_expr(err, lval, rval, op); - if (!error_empty(err)) { - goto generic_error; - } - return result; + Value* result = parse_binary_expr(err, lval, rval, op); + if (!error_empty(err)) { + goto generic_error; + } + return result; syntax_error: - error_push(err, "%s: syntax error, expected binary expression", __func__); + error_push(err, "%s: syntax error, expected binary expression", __func__); generic_error: - return NULL; + return NULL; } static Value* parser_next(Error* err, Mfile* m) @@ -189,22 +273,22 @@ static Value* parser_next(Error* err, Mfile* m) } else if (!error_empty(err)) { return NULL; } - Value* result; - switch (t->type) { - case TOKEN_INTEGER: { + case TOKEN_INTEGER: + case TOKEN_FLOATING: + { result = parser_handle_binary_expr(err, t, m); if (!error_empty(err)) { goto syntax_error; } + break; } default: syntax_error: { - error_push(err, "syntax error: unexpected token %s", token_type_str[t->type]); + error_push(err, "(%s) syntax error: unexpected token %s", __func__, token_type_str[t->type]); return NULL; } } - token_print(err, t); return result; }