diff --git a/TODO.TXT b/TODO.TXT index 2819333..0655053 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -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 diff --git a/biner.l b/biner.l index 6a7f848..405c8d0 100644 --- a/biner.l +++ b/biner.l @@ -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; } diff --git a/biner.y b/biner.y index becd9da..2738171 100644 --- a/biner.y +++ b/biner.y @@ -91,13 +91,13 @@ resolve_constant_( } %token EQUAL NEQUAL LESS_EQUAL GREATER_EQUAL -%token CONST ENUM STRUCT +%token CONST ENUM STRUCT UNION %token IDENT %token INTEGER; %type decl_list decl %type enum_member_list enum_member -%type struct_member_list struct_member +%type struct_member_list struct_member union_member_list union_member %type struct_member_type array_struct_member_type unqualified_struct_member_type %type 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)) { @@ -359,8 +385,9 @@ static inline biner_zone_ptr(biner_tree_decl_t) create_decl_( .type = type, .body = body, }; - ctx.last_decl = decl; - ctx.last_body = 0; + ctx.last_decl = decl; + ctx.last_enum = 0; + ctx.last_struct = 0; return decl; } diff --git a/main.c b/main.c index bfe2ee9..722c576 100644 --- a/main.c +++ b/main.c @@ -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) { diff --git a/tree.h b/tree.h index 1336138..32f9cf8 100644 --- a/tree.h +++ b/tree.h @@ -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_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_;