Adds union feature.

This commit is contained in:
falsycat 2020-12-26 00:00:00 +00:00
parent e34d4ca1a8
commit b96fbb6eb2
5 changed files with 43 additions and 18 deletions

View File

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

View File

@ -32,6 +32,7 @@ H [0-9A-Fa-f]
"const" { count_(); return CONST; }
"enum" { count_(); return ENUM; }
"struct" { count_(); return STRUCT; }
"union" { count_(); return UNION; }
{I}({I}|{D})* { yylval.ptr = strnew_(); count_(); return IDENT; }

45
biner.y
View File

@ -91,13 +91,13 @@ resolve_constant_(
}
%token EQUAL NEQUAL LESS_EQUAL GREATER_EQUAL
%token CONST ENUM STRUCT
%token CONST ENUM STRUCT UNION
%token <ptr> IDENT
%token <i> INTEGER;
%type <ptr> decl_list decl
%type <ptr> enum_member_list enum_member
%type <ptr> struct_member_list struct_member
%type <ptr> struct_member_list struct_member union_member_list union_member
%type <ptr> struct_member_type array_struct_member_type unqualified_struct_member_type
%type <ptr> expr compare_expr add_expr mul_expr unary_expr operand
@ -167,21 +167,48 @@ enum_member
;
struct_member_list
: struct_member {
: struct_member ';' {
$$ = ctx.last_struct = $1;
}
| struct_member_list struct_member {
ref(biner_tree_struct_member_t, $2)->prev = $1;
| struct_member_list struct_member ';' {
$$ = ctx.last_struct = $2;
biner_tree_struct_member_t* list = ref(biner_tree_struct_member_t, $1);
const size_t index = list->index + 1;
biner_zone_ptr(biner_tree_struct_member_t) itr = $2;
while (itr) {
biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, itr);
m->index = index;
itr = m->prev;
if (itr == 0) m->prev = $1;
}
}
;
union_member_list
: union_member ';' {
$$ = $1;
}
| union_member_list union_member ';' {
$$ = $2;
ref(biner_tree_struct_member_t, $2)->prev = $1;
}
;
struct_member
: struct_member_type IDENT ';' {
: union_member
| UNION '{' union_member_list '}' {
$$ = $3;
}
;
union_member
: struct_member_type IDENT {
$$ = create_struct_member_(0, $1, $2);
if ($$ == 0) YYABORT;
}
| '(' expr ')' struct_member_type IDENT ';' {
| '(' expr ')' struct_member_type IDENT {
$$ = create_struct_member_($2, $4, $5);
if ($$ == 0) YYABORT;
}
@ -214,7 +241,6 @@ unqualified_struct_member_type
*t = (biner_tree_struct_member_type_t) {
.qualifier = BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_NONE,
};
const biner_zone_ptr(biner_tree_decl_t) decl = find_decl_by_name_($1);
if (decl == 0) {
if (!unstringify_struct_member_type_name_(&t->name, $1)) {
@ -360,7 +386,8 @@ static inline biner_zone_ptr(biner_tree_decl_t) create_decl_(
.body = body,
};
ctx.last_decl = decl;
ctx.last_body = 0;
ctx.last_enum = 0;
ctx.last_struct = 0;
return decl;
}

2
main.c
View File

@ -28,7 +28,7 @@ static inline void print_struct_(
const biner_tree_struct_member_t* member =
(const biner_tree_struct_member_t*) (zone + decl->struct_);
while ((uintptr_t) member != (uintptr_t) zone) {
printf(" ");
printf(" %2zu ", member->index);
const biner_tree_struct_member_type_t* type =
(const biner_tree_struct_member_type_t*) (zone + member->type);
if (type->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {

5
tree.h
View File

@ -84,6 +84,7 @@ typedef struct biner_tree_struct_member_type_t {
} biner_tree_struct_member_type_t;
typedef struct biner_tree_struct_member_t {
size_t index;
biner_zone_ptr(char) name;
biner_zone_ptr(biner_tree_struct_member_type_t) type;
biner_zone_ptr(biner_tree_expr_t) condition;
@ -135,12 +136,8 @@ typedef struct biner_tree_parse_context_t {
biner_zone_ptr(biner_tree_root_t) root;
biner_zone_ptr(biner_tree_decl_t) last_decl;
union {
biner_zone_ptr(void) last_body;
biner_zone_ptr(biner_tree_struct_member_t) last_struct;
biner_zone_ptr(biner_tree_enum_member_t) last_enum;
};
} biner_tree_parse_context_t;
extern biner_tree_parse_context_t biner_tree_parse_context_;