jaf: support cast expressions

Support both function-style casts (eg. "int(12.3)") and C-style casts
(eg. "(int)12.3").
This commit is contained in:
Nunuhara Cabbage
2020-06-13 23:00:21 -07:00
parent e618017e78
commit 5ecdd1ceed
5 changed files with 172 additions and 35 deletions
+14 -2
View File
@@ -47,6 +47,10 @@ enum jaf_expression_type {
JAF_EXP_UNARY,
JAF_EXP_BINARY,
JAF_EXP_TERNARY,
//JAF_EXP_SUBSCRIPT,
//JAF_EXP_FUNCALL,
JAF_EXP_CAST,
//JAF_EXP_MEMBER,
};
enum jaf_operator {
@@ -113,6 +117,11 @@ struct jaf_expression {
struct jaf_expression *consequent;
struct jaf_expression *alternative;
};
// cast
struct {
enum jaf_type type;
struct jaf_expression *expr;
} cast;
};
};
@@ -221,14 +230,17 @@ struct jaf_block {
struct jaf_block_item **items;
};
struct jaf_expression *jaf_integer(struct string *text);
struct jaf_expression *jaf_float(struct string *text);
struct jaf_expression *jaf_integer(int i);
struct jaf_expression *jaf_parse_integer(struct string *text);
struct jaf_expression *jaf_float(float f);
struct jaf_expression *jaf_parse_float(struct string *text);
struct jaf_expression *jaf_string(struct string *text);
struct jaf_expression *jaf_identifier(struct string *name);
struct jaf_expression *jaf_unary_expr(enum jaf_operator op, struct jaf_expression *expr);
struct jaf_expression *jaf_binary_expr(enum jaf_operator op, struct jaf_expression *lhs, struct jaf_expression *rhs);
struct jaf_expression *jaf_ternary_expr(struct jaf_expression *test, struct jaf_expression *cons, struct jaf_expression *alt);
struct jaf_expression *jaf_seq_expr(struct jaf_expression *head, struct jaf_expression *tail);
struct jaf_expression *jaf_cast_expression(enum jaf_type type, struct jaf_expression *expr);
struct jaf_type_specifier *jaf_type(enum jaf_type type);
struct jaf_type_specifier *jaf_struct(struct string *name, struct jaf_block *fields);
+52 -14
View File
@@ -30,33 +30,48 @@ static struct jaf_expression *jaf_expr(enum jaf_expression_type type, enum jaf_o
return e;
}
struct jaf_expression *jaf_integer(struct string *text)
struct jaf_expression *jaf_integer(int i)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_INT, 0);
char *endptr;
errno = 0;
e->i = strtol(text->text, &endptr, 0);
if (errno || *endptr != '\0')
ERROR("Invalid integer constant");
free_string(text);
e->derived_type = JAF_INT;
e->i = i;
return e;
}
struct jaf_expression *jaf_float(struct string *text)
struct jaf_expression *jaf_parse_integer(struct string *text)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_FLOAT, 0);
char *endptr;
errno = 0;
e->f = strtof(text->text, &endptr);
int i = strtol(text->text, &endptr, 0);
if (errno || *endptr != '\0')
ERROR("Invalid integer constant");
free_string(text);
return jaf_integer(i);
}
struct jaf_expression *jaf_float(float f)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_FLOAT, 0);
e->derived_type = JAF_FLOAT;
e->f = f;
return e;
}
struct jaf_expression *jaf_parse_float(struct string *text)
{
char *endptr;
errno = 0;
float f = strtof(text->text, &endptr);
if (errno || *endptr != '\0')
ERROR("Invalid floating point constant");
free_string(text);
return e;
return jaf_float(f);
}
struct jaf_expression *jaf_string(struct string *text)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_STRING, 0);
e->derived_type = JAF_STRING;
e->s = text;
return e;
}
@@ -97,6 +112,14 @@ struct jaf_expression *jaf_seq_expr(struct jaf_expression *head, struct jaf_expr
ERROR("Sequence expressions not supported");
}
struct jaf_expression *jaf_cast_expression(enum jaf_type type, struct jaf_expression *expr)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_CAST, 0);
e->cast.type = type;
e->cast.expr = expr;
return e;
}
struct jaf_type_specifier *jaf_type(enum jaf_type type)
{
struct jaf_type_specifier *p = xcalloc(1, sizeof(struct jaf_type_specifier));
@@ -343,15 +366,30 @@ void jaf_free_expr(struct jaf_expression *expr)
{
if (!expr)
return;
if (expr->type == JAF_EXP_UNARY) {
switch (expr->type) {
case JAF_EXP_VOID:
case JAF_EXP_INT:
case JAF_EXP_FLOAT:
break;
case JAF_EXP_STRING:
case JAF_EXP_IDENTIFIER:
free_string(expr->s);
break;
case JAF_EXP_UNARY:
jaf_free_expr(expr->expr);
} else if (expr->type == JAF_EXP_BINARY) {
break;
case JAF_EXP_BINARY:
jaf_free_expr(expr->lhs);
jaf_free_expr(expr->rhs);
} else if (expr->type == JAF_EXP_TERNARY) {
break;
case JAF_EXP_TERNARY:
jaf_free_expr(expr->condition);
jaf_free_expr(expr->consequent);
jaf_free_expr(expr->alternative);
break;
case JAF_EXP_CAST:
jaf_free_expr(expr->cast.expr);
break;
}
free(expr);
}
+67
View File
@@ -15,6 +15,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include "system4.h"
#include "system4/string.h"
#include "jaf.h"
@@ -220,6 +221,70 @@ struct jaf_expression *jaf_simplify_ternary(struct jaf_expression *in)
return in;
}
struct jaf_expression *jaf_simplify_cast(struct jaf_expression *in)
{
in->cast.expr = jaf_simplify(in->cast.expr);
if (in->cast.type == JAF_INT) {
if (in->cast.expr->type == JAF_EXP_INT) {
struct jaf_expression *r = in->cast.expr;
free(in);
return r;
}
if (in->cast.expr->type == JAF_EXP_FLOAT) {
struct jaf_expression *r = jaf_integer((int)in->cast.expr->f);
jaf_free_expr(in);
return r;
}
if (in->cast.expr->type == JAF_EXP_STRING) {
struct jaf_expression *r = jaf_parse_integer(string_dup(in->cast.expr->s));
jaf_free_expr(in);
return r;
}
}
if (in->cast.type == JAF_FLOAT) {
if (in->cast.expr->type == JAF_EXP_FLOAT) {
struct jaf_expression *r = in->cast.expr;
free(in);
return r;
}
if (in->cast.expr->type == JAF_EXP_INT) {
struct jaf_expression *r = jaf_float((float)in->cast.expr->i);
jaf_free_expr(in);
return r;
}
if (in->cast.expr->type == JAF_EXP_STRING) {
struct jaf_expression *r = jaf_parse_float(string_dup(in->cast.expr->s));
jaf_free_expr(in);
return r;
}
}
if (in->cast.type == JAF_STRING) {
if (in->cast.expr->type == JAF_EXP_STRING) {
struct jaf_expression *r = in->cast.expr;
free(in);
return r;
}
if (in->cast.expr->type == JAF_EXP_INT) {
char buf[512];
snprintf(buf, 512, "%i", in->cast.expr->i);
WARNING("CAST %d to string: %s", in->cast.expr->i, buf);
jaf_free_expr(in);
return jaf_string(make_string(buf, strlen(buf)));
}
if (in->cast.expr->type == JAF_EXP_FLOAT) {
char buf[512];
snprintf(buf, 512, "%f", in->cast.expr->f);
jaf_free_expr(in);
return jaf_string(make_string(buf, strlen(buf)));
}
}
return in;
}
/*
* Simplify an expression by evaluating the constant parts.
*/
@@ -238,6 +303,8 @@ struct jaf_expression *jaf_simplify(struct jaf_expression *in)
return jaf_simplify_binary(in);
case JAF_EXP_TERNARY:
return jaf_simplify_ternary(in);
case JAF_EXP_CAST:
return jaf_simplify_cast(in);
}
ERROR("Invalid expression type");
}
+20 -16
View File
@@ -51,7 +51,7 @@ void yyerror(const char *s);
%token CASE DEFAULT IF ELSE SYM_SWITCH WHILE DO FOR GOTO CONTINUE BREAK SYM_RETURN
%type <token> unary_operator assignment_operator type_qualifier
%type <token> unary_operator assignment_operator type_qualifier atomic_type_specifier
%type <string> string param_identifer
%type <expression> initializer
%type <expression> postfix_expression unary_expression cast_expression
@@ -89,8 +89,8 @@ primary_expression
;
constant
: I_CONSTANT { $$ = jaf_integer($1); } /* includes character_constant */
| F_CONSTANT { $$ = jaf_float($1); }
: I_CONSTANT { $$ = jaf_parse_integer($1); } /* includes character_constant */
| F_CONSTANT { $$ = jaf_parse_float($1); }
| ENUMERATION_CONSTANT { ERROR("Enums not supported"); } /* after it has been defined as such */
;
@@ -108,7 +108,7 @@ postfix_expression
: primary_expression { $$ = $1; }
| postfix_expression '[' expression ']' { ERROR("Arrays not supported"); }
| postfix_expression '(' ')' { ERROR("Function calls not supported"); }
| type_specifier '(' expression ')' { ERROR("Cast not supported"); }
| atomic_type_specifier '(' expression ')' { $$ = jaf_cast_expression($1, $3); }
| postfix_expression '(' argument_expression_list ')' { ERROR("Function calls not supported"); }
| postfix_expression '.' IDENTIFIER { ERROR("Struct members not supported"); }
| postfix_expression INC_OP { $$ = jaf_unary_expr(JAF_POST_INC, $1); }
@@ -138,8 +138,8 @@ unary_operator
;
cast_expression
: unary_expression { $$ = $1; }
| '(' type_specifier ')' cast_expression { ERROR("Cast not supported"); }
: unary_expression { $$ = $1; }
| '(' atomic_type_specifier ')' cast_expression { $$ = jaf_cast_expression($2, $4); }
;
multiplicative_expression
@@ -254,17 +254,21 @@ init_declarator
| declarator { $$ = $1; }
;
atomic_type_specifier
: VOID { $$ = JAF_VOID; }
| CHAR { $$ = JAF_INT; }
| INT { $$ = JAF_INT; }
| LONG { $$ = JAF_INT; }
| FLOAT { $$ = JAF_FLOAT; }
| BOOL { $$ = JAF_INT; }
| STRING { $$ = JAF_STRING; }
;
type_specifier
: VOID { $$ = jaf_type(JAF_VOID); }
| CHAR { $$ = jaf_type(JAF_INT); }
| INT { $$ = jaf_type(JAF_INT); }
| LONG { $$ = jaf_type(JAF_INT); }
| FLOAT { $$ = jaf_type(JAF_FLOAT); }
| BOOL { $$ = jaf_type(JAF_INT); }
| STRING { $$ = jaf_type(JAF_STRING); }
| struct_specifier { $$ = $1; }
| enum_specifier { ERROR("Enums not supported"); }
| TYPEDEF_NAME { $$ = jaf_typedef($1); } /* after it has been defined as such */
: atomic_type_specifier { $$ = jaf_type($1); }
| struct_specifier { $$ = $1; }
| enum_specifier { ERROR("Enums not supported"); }
| TYPEDEF_NAME { $$ = jaf_typedef($1); }
;
struct_specifier
+19 -3
View File
@@ -19,10 +19,24 @@
#include "jaf.h"
// TODO: better error messages
#define TYPE_ERROR(expr, expected) ERROR("Type error")
#define TYPE_ERROR(expr, expected) ERROR("Type error (expected %s; got %s)", jaf_typestr(expected), jaf_typestr(expr->derived_type))
#define TYPE_CHECK(expr, expected) { if (expr->derived_type != expected) TYPE_ERROR(expr, expected); }
#define TYPE_CHECK_NUMERIC(expr) { if (expr->derived_type != JAF_INT && expr->derived_type != JAF_FLOAT) TYPE_ERROR(expr, JAF_INT); }
static const char *jaf_typestr(enum jaf_type type)
{
switch (type) {
case JAF_VOID: return "void";
case JAF_INT: return "int";
case JAF_FLOAT: return "float";
case JAF_STRING: return "string";
case JAF_STRUCT: return "struct";
case JAF_ENUM: return "enum";
case JAF_TYPEDEF: return "typedef";
}
return "unknown";
}
static enum jaf_type jaf_type_check_numeric(struct jaf_expression *expr)
{
if (expr->derived_type != JAF_INT && expr->derived_type != JAF_FLOAT)
@@ -143,6 +157,8 @@ static enum jaf_type jaf_check_types_ternary(struct jaf_expression *expr)
static enum jaf_type _jaf_check_types(struct jaf_expression *expr)
{
switch (expr->type) {
case JAF_EXP_VOID:
return JAF_VOID;
case JAF_EXP_INT:
return JAF_INT;
case JAF_EXP_FLOAT:
@@ -158,8 +174,8 @@ static enum jaf_type _jaf_check_types(struct jaf_expression *expr)
return jaf_check_types_binary(expr);
case JAF_EXP_TERNARY:
return jaf_check_types_ternary(expr);
default:
break;
case JAF_EXP_CAST:
return expr->cast.type;
}
ERROR("Unhandled expression type");
}