From 5ecdd1ceed78ce8443fe4958d60cab874f2c683c Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Sat, 13 Jun 2020 23:00:21 -0700 Subject: [PATCH] jaf: support cast expressions Support both function-style casts (eg. "int(12.3)") and C-style casts (eg. "(int)12.3"). --- src/tools/ainedit/jaf.h | 16 +++++++- src/tools/ainedit/jaf_ast.c | 66 ++++++++++++++++++++++++++------- src/tools/ainedit/jaf_eval.c | 67 ++++++++++++++++++++++++++++++++++ src/tools/ainedit/jaf_parser.y | 36 ++++++++++-------- src/tools/ainedit/jaf_types.c | 22 +++++++++-- 5 files changed, 172 insertions(+), 35 deletions(-) diff --git a/src/tools/ainedit/jaf.h b/src/tools/ainedit/jaf.h index 2c89f7e..0955666 100644 --- a/src/tools/ainedit/jaf.h +++ b/src/tools/ainedit/jaf.h @@ -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); diff --git a/src/tools/ainedit/jaf_ast.c b/src/tools/ainedit/jaf_ast.c index ff26dd1..47cf071 100644 --- a/src/tools/ainedit/jaf_ast.c +++ b/src/tools/ainedit/jaf_ast.c @@ -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); } diff --git a/src/tools/ainedit/jaf_eval.c b/src/tools/ainedit/jaf_eval.c index 2687ec5..a1276b1 100644 --- a/src/tools/ainedit/jaf_eval.c +++ b/src/tools/ainedit/jaf_eval.c @@ -15,6 +15,7 @@ */ #include +#include #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"); } diff --git a/src/tools/ainedit/jaf_parser.y b/src/tools/ainedit/jaf_parser.y index 3e97a26..bba2f19 100644 --- a/src/tools/ainedit/jaf_parser.y +++ b/src/tools/ainedit/jaf_parser.y @@ -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 unary_operator assignment_operator type_qualifier +%type unary_operator assignment_operator type_qualifier atomic_type_specifier %type string param_identifer %type initializer %type 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 diff --git a/src/tools/ainedit/jaf_types.c b/src/tools/ainedit/jaf_types.c index 808dad8..10b17ea 100644 --- a/src/tools/ainedit/jaf_types.c +++ b/src/tools/ainedit/jaf_types.c @@ -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"); }