From e34d4ca1a8fbaf18edc95f6cd6b6a020334d69f5 Mon Sep 17 00:00:00 2001 From: falsycat Date: Sat, 26 Dec 2020 00:00:00 +0000 Subject: [PATCH] Adds conditional switching feature. --- TODO.TXT | 2 +- biner.l | 7 +++- biner.y | 100 ++++++++++++++++++++++++++++++++++++++++++------------- main.c | 7 +++- tree.h | 11 ++++-- 5 files changed, 99 insertions(+), 28 deletions(-) diff --git a/TODO.TXT b/TODO.TXT index ba18068..2819333 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -6,7 +6,7 @@ X constant resolving in expression X check if an expression is static/dynamic X enum support X constant support - conditional switching support +X conditional switching support union support transpiler for C release 1.0.0 diff --git a/biner.l b/biner.l index 49d7067..6a7f848 100644 --- a/biner.l +++ b/biner.l @@ -24,6 +24,11 @@ H [0-9A-Fa-f] "//".* count_(); [/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */ +"==" { count_(); return EQUAL; } +"!=" { count_(); return NEQUAL; } +"<=" { count_(); return LESS_EQUAL; } +">=" { count_(); return GREATER_EQUAL; } + "const" { count_(); return CONST; } "enum" { count_(); return ENUM; } "struct" { count_(); return STRUCT; } @@ -33,7 +38,7 @@ H [0-9A-Fa-f] {D}+ { yylval.i = parse_int_(10); count_(); return INTEGER; } 0[xX]{H}+ { yylval.i = parse_int_(16); count_(); return INTEGER; } -[\+\-\*\/\=\.\(\)[\]\{\}\;\,] { count_(); return yytext[0]; } +[\+\-\*\/\!\=\<\>\.\(\)[\]\{\}\;\,] { count_(); return yytext[0]; } (.|\n) count_(); diff --git a/biner.y b/biner.y index e498d55..becd9da 100644 --- a/biner.y +++ b/biner.y @@ -42,6 +42,13 @@ find_enum_member_by_name_( biner_zone_ptr(char) name ); +static inline biner_zone_ptr(biner_tree_struct_member_t) +create_struct_member_( + biner_zone_ptr(biner_tree_expr_t) condition, + biner_zone_ptr(biner_tree_struct_member_type_t) type, + biner_zone_ptr(char) name +); + static inline bool unstringify_struct_member_type_name_( biner_tree_struct_member_type_name_t* name, @@ -83,6 +90,7 @@ resolve_constant_( uintptr_t ptr; } +%token EQUAL NEQUAL LESS_EQUAL GREATER_EQUAL %token CONST ENUM STRUCT %token IDENT %token INTEGER; @@ -91,7 +99,7 @@ resolve_constant_( %type enum_member_list enum_member %type struct_member_list struct_member %type struct_member_type array_struct_member_type unqualified_struct_member_type -%type expr add_expr mul_expr operand +%type expr compare_expr add_expr mul_expr unary_expr operand %start decl_list @@ -170,20 +178,12 @@ struct_member_list struct_member : struct_member_type IDENT ';' { - if (resolve_constant_($2) != 0) { - yyerrorf("duplicated symbol name, '%s'", ref(char, $2)); - YYABORT; - } - if (find_struct_member_by_name_(ctx.last_struct, $2) != 0) { - yyerrorf("duplicated struct member of '%s'", ref(char, $2)); - YYABORT; - } - $$ = alloc_(biner_tree_struct_member_t); - *ref(biner_tree_struct_member_t, $$) = - (biner_tree_struct_member_t) { - .type = $1, - .name = $2, - }; + $$ = create_struct_member_(0, $1, $2); + if ($$ == 0) YYABORT; + } + | '(' expr ')' struct_member_type IDENT ';' { + $$ = create_struct_member_($2, $4, $5); + if ($$ == 0) YYABORT; } ; @@ -229,7 +229,29 @@ unqualified_struct_member_type ; expr - : add_expr { $$ = $1; } + : compare_expr + ; + +compare_expr + : add_expr + | compare_expr EQUAL add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_EQUAL, $3); + } + | compare_expr NEQUAL add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_NEQUAL, $3); + } + | compare_expr '>' add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_GREATER, $3); + } + | compare_expr '<' add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_LESS, $3); + } + | compare_expr GREATER_EQUAL add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_GREATER_EQUAL, $3); + } + | compare_expr LESS_EQUAL add_expr { + $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_LESS_EQUAL, $3); + } ; add_expr @@ -243,15 +265,22 @@ add_expr ; mul_expr - : operand - | mul_expr '*' operand { + : unary_expr + | mul_expr '*' unary_expr { $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_MUL, $3); } - | mul_expr '/' operand { + | mul_expr '/' unary_expr { $$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_DIV, $3); } ; +unary_expr + : operand + | '!' operand { + $$ = create_operator_($2, BINER_TREE_EXPR_TYPE_OPERATOR_NOT, 0); + } + ; + operand : INTEGER { $$ = alloc_(biner_tree_expr_t); @@ -295,13 +324,15 @@ operand yyerrorf("unknown member '%s'", ref(char, $3)); YYABORT; } - $$ = alloc_(biner_tree_struct_member_reference_t); - *ref(biner_tree_struct_member_reference_t, $$) = + biner_zone_ptr(biner_tree_struct_member_reference_t) r = + alloc_(biner_tree_struct_member_reference_t); + *ref(biner_tree_struct_member_reference_t, r) = (biner_tree_struct_member_reference_t) { .member = m, .prev = expr->r, }; - expr->r = $$; + expr->r = r; + $$ = $1; /* A shared expression such as constant cannot have a reference to member. * So modification of the expression doesn't cause any side effects. */ @@ -344,6 +375,29 @@ static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_( return 0; } +static inline biner_zone_ptr(biner_tree_struct_member_t) create_struct_member_( + biner_zone_ptr(biner_tree_expr_t) condition, + biner_zone_ptr(biner_tree_struct_member_type_t) type, + biner_zone_ptr(char) name) { + if (resolve_constant_(name) != 0) { + yyerrorf("duplicated symbol name, '%s'", ref(char, name)); + return 0; + } + if (find_struct_member_by_name_(ctx.last_struct, name) != 0) { + yyerrorf("duplicated struct member of '%s'", ref(char, name)); + return 0; + } + const biner_zone_ptr(biner_tree_struct_member_t) ret = + alloc_(biner_tree_struct_member_t); + *ref(biner_tree_struct_member_t, ret) = + (biner_tree_struct_member_t) { + .type = type, + .condition = condition, + .name = name, + }; + return ret; +} + static inline biner_zone_ptr(biner_tree_expr_t) find_enum_member_by_name_( biner_zone_ptr(biner_tree_enum_member_t) tail_member, biner_zone_ptr(char) name) { @@ -424,7 +478,7 @@ static inline biner_zone_ptr(biner_tree_expr_t) create_operator_( biner_zone_ptr(biner_tree_expr_t) expr = alloc_(biner_tree_expr_t); *ref(biner_tree_expr_t, expr) = (biner_tree_expr_t) { .type = type, - .dynamic = lexpr->dynamic || rexpr->dynamic, + .dynamic = (l && lexpr->dynamic) || (r && rexpr->dynamic), .operands = {l, r}, }; return expr; diff --git a/main.c b/main.c index 5783388..bfe2ee9 100644 --- a/main.c +++ b/main.c @@ -39,7 +39,12 @@ static inline void print_struct_( printf("%8s ", biner_tree_struct_member_type_name_string_map[type->name]); } - printf("%s\n", zone + member->name); + if (member->condition == 0) { + printf("%s", zone + member->name); + } else { + printf("(%s)", zone + member->name); + } + printf("\n"); member = (const biner_tree_struct_member_t*) (zone + member->prev); } } diff --git a/tree.h b/tree.h index 1cc290e..1336138 100644 --- a/tree.h +++ b/tree.h @@ -19,6 +19,13 @@ typedef struct biner_tree_decl_t biner_tree_decl_t; typedef enum biner_tree_expr_type_t { BINER_TREE_EXPR_TYPE_OPERAND_INTEGER, BINER_TREE_EXPR_TYPE_OPERAND_REFERENCE, + BINER_TREE_EXPR_TYPE_OPERATOR_EQUAL, + BINER_TREE_EXPR_TYPE_OPERATOR_NEQUAL, + BINER_TREE_EXPR_TYPE_OPERATOR_GREATER_EQUAL, + BINER_TREE_EXPR_TYPE_OPERATOR_LESS_EQUAL, + BINER_TREE_EXPR_TYPE_OPERATOR_GREATER, + BINER_TREE_EXPR_TYPE_OPERATOR_LESS, + BINER_TREE_EXPR_TYPE_OPERATOR_NOT, BINER_TREE_EXPR_TYPE_OPERATOR_ADD, BINER_TREE_EXPR_TYPE_OPERATOR_SUB, BINER_TREE_EXPR_TYPE_OPERATOR_MUL, @@ -79,8 +86,8 @@ typedef struct biner_tree_struct_member_type_t { typedef struct biner_tree_struct_member_t { biner_zone_ptr(char) name; biner_zone_ptr(biner_tree_struct_member_type_t) type; - - biner_zone_ptr(biner_tree_struct_member_t) prev; + biner_zone_ptr(biner_tree_expr_t) condition; + biner_zone_ptr(biner_tree_struct_member_t) prev; } biner_tree_struct_member_t; typedef struct biner_tree_struct_member_reference_t {