Adds conditional switching feature.

This commit is contained in:
falsycat 2020-12-26 00:00:00 +00:00
parent b4957586e4
commit e34d4ca1a8
5 changed files with 99 additions and 28 deletions

View File

@ -6,7 +6,7 @@ X constant resolving in expression
X check if an expression is static/dynamic X check if an expression is static/dynamic
X enum support X enum support
X constant support X constant support
conditional switching support X conditional switching support
union support union support
transpiler for C transpiler for C
release 1.0.0 release 1.0.0

View File

@ -24,6 +24,11 @@ H [0-9A-Fa-f]
"//".* count_(); "//".* count_();
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */ [/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */
"==" { count_(); return EQUAL; }
"!=" { count_(); return NEQUAL; }
"<=" { count_(); return LESS_EQUAL; }
">=" { count_(); return GREATER_EQUAL; }
"const" { count_(); return CONST; } "const" { count_(); return CONST; }
"enum" { count_(); return ENUM; } "enum" { count_(); return ENUM; }
"struct" { count_(); return STRUCT; } "struct" { count_(); return STRUCT; }
@ -33,7 +38,7 @@ H [0-9A-Fa-f]
{D}+ { yylval.i = parse_int_(10); count_(); return INTEGER; } {D}+ { yylval.i = parse_int_(10); count_(); return INTEGER; }
0[xX]{H}+ { yylval.i = parse_int_(16); count_(); return INTEGER; } 0[xX]{H}+ { yylval.i = parse_int_(16); count_(); return INTEGER; }
[\+\-\*\/\=\.\(\)[\]\{\}\;\,] { count_(); return yytext[0]; } [\+\-\*\/\!\=\<\>\.\(\)[\]\{\}\;\,] { count_(); return yytext[0]; }
(.|\n) count_(); (.|\n) count_();

98
biner.y
View File

@ -42,6 +42,13 @@ find_enum_member_by_name_(
biner_zone_ptr(char) 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 static inline bool
unstringify_struct_member_type_name_( unstringify_struct_member_type_name_(
biner_tree_struct_member_type_name_t* name, biner_tree_struct_member_type_name_t* name,
@ -83,6 +90,7 @@ resolve_constant_(
uintptr_t ptr; uintptr_t ptr;
} }
%token EQUAL NEQUAL LESS_EQUAL GREATER_EQUAL
%token CONST ENUM STRUCT %token CONST ENUM STRUCT
%token <ptr> IDENT %token <ptr> IDENT
%token <i> INTEGER; %token <i> INTEGER;
@ -91,7 +99,7 @@ resolve_constant_(
%type <ptr> enum_member_list enum_member %type <ptr> enum_member_list enum_member
%type <ptr> struct_member_list struct_member %type <ptr> struct_member_list struct_member
%type <ptr> struct_member_type array_struct_member_type unqualified_struct_member_type %type <ptr> struct_member_type array_struct_member_type unqualified_struct_member_type
%type <ptr> expr add_expr mul_expr operand %type <ptr> expr compare_expr add_expr mul_expr unary_expr operand
%start decl_list %start decl_list
@ -170,20 +178,12 @@ struct_member_list
struct_member struct_member
: struct_member_type IDENT ';' { : struct_member_type IDENT ';' {
if (resolve_constant_($2) != 0) { $$ = create_struct_member_(0, $1, $2);
yyerrorf("duplicated symbol name, '%s'", ref(char, $2)); if ($$ == 0) YYABORT;
YYABORT;
} }
if (find_struct_member_by_name_(ctx.last_struct, $2) != 0) { | '(' expr ')' struct_member_type IDENT ';' {
yyerrorf("duplicated struct member of '%s'", ref(char, $2)); $$ = create_struct_member_($2, $4, $5);
YYABORT; if ($$ == 0) YYABORT;
}
$$ = alloc_(biner_tree_struct_member_t);
*ref(biner_tree_struct_member_t, $$) =
(biner_tree_struct_member_t) {
.type = $1,
.name = $2,
};
} }
; ;
@ -229,7 +229,29 @@ unqualified_struct_member_type
; ;
expr 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 add_expr
@ -243,15 +265,22 @@ add_expr
; ;
mul_expr mul_expr
: operand : unary_expr
| mul_expr '*' operand { | mul_expr '*' unary_expr {
$$ = create_operator_($1, BINER_TREE_EXPR_TYPE_OPERATOR_MUL, $3); $$ = 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); $$ = 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 operand
: INTEGER { : INTEGER {
$$ = alloc_(biner_tree_expr_t); $$ = alloc_(biner_tree_expr_t);
@ -295,13 +324,15 @@ operand
yyerrorf("unknown member '%s'", ref(char, $3)); yyerrorf("unknown member '%s'", ref(char, $3));
YYABORT; YYABORT;
} }
$$ = alloc_(biner_tree_struct_member_reference_t); biner_zone_ptr(biner_tree_struct_member_reference_t) r =
*ref(biner_tree_struct_member_reference_t, $$) = alloc_(biner_tree_struct_member_reference_t);
*ref(biner_tree_struct_member_reference_t, r) =
(biner_tree_struct_member_reference_t) { (biner_tree_struct_member_reference_t) {
.member = m, .member = m,
.prev = expr->r, .prev = expr->r,
}; };
expr->r = $$; expr->r = r;
$$ = $1;
/* A shared expression such as constant cannot have a reference to member. /* A shared expression such as constant cannot have a reference to member.
* So modification of the expression doesn't cause any side effects. * 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; 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_( 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(biner_tree_enum_member_t) tail_member,
biner_zone_ptr(char) name) { 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); biner_zone_ptr(biner_tree_expr_t) expr = alloc_(biner_tree_expr_t);
*ref(biner_tree_expr_t, expr) = (biner_tree_expr_t) { *ref(biner_tree_expr_t, expr) = (biner_tree_expr_t) {
.type = type, .type = type,
.dynamic = lexpr->dynamic || rexpr->dynamic, .dynamic = (l && lexpr->dynamic) || (r && rexpr->dynamic),
.operands = {l, r}, .operands = {l, r},
}; };
return expr; return expr;

7
main.c
View File

@ -39,7 +39,12 @@ static inline void print_struct_(
printf("%8s ", printf("%8s ",
biner_tree_struct_member_type_name_string_map[type->name]); 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); member = (const biner_tree_struct_member_t*) (zone + member->prev);
} }
} }

9
tree.h
View File

@ -19,6 +19,13 @@ typedef struct biner_tree_decl_t biner_tree_decl_t;
typedef enum biner_tree_expr_type_t { typedef enum biner_tree_expr_type_t {
BINER_TREE_EXPR_TYPE_OPERAND_INTEGER, BINER_TREE_EXPR_TYPE_OPERAND_INTEGER,
BINER_TREE_EXPR_TYPE_OPERAND_REFERENCE, 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_ADD,
BINER_TREE_EXPR_TYPE_OPERATOR_SUB, BINER_TREE_EXPR_TYPE_OPERATOR_SUB,
BINER_TREE_EXPR_TYPE_OPERATOR_MUL, BINER_TREE_EXPR_TYPE_OPERATOR_MUL,
@ -79,7 +86,7 @@ typedef struct biner_tree_struct_member_type_t {
typedef struct biner_tree_struct_member_t { typedef struct biner_tree_struct_member_t {
biner_zone_ptr(char) name; biner_zone_ptr(char) name;
biner_zone_ptr(biner_tree_struct_member_type_t) type; biner_zone_ptr(biner_tree_struct_member_type_t) type;
biner_zone_ptr(biner_tree_expr_t) condition;
biner_zone_ptr(biner_tree_struct_member_t) prev; biner_zone_ptr(biner_tree_struct_member_t) prev;
} biner_tree_struct_member_t; } biner_tree_struct_member_t;