Adds enum feature.

This commit is contained in:
falsycat 2020-12-26 00:00:00 +00:00
parent c9ec7332d9
commit 9d21e9809a
5 changed files with 204 additions and 60 deletions

View File

@ -4,7 +4,7 @@ X user-defined type resolving
X make enum for generic types X make enum for generic types
X constant resolving in expression X constant resolving in expression
X check if an expression is static/dynamic X check if an expression is static/dynamic
enum support X enum support
constant support constant support
conditional switching support conditional switching support
union support union support

View File

@ -24,6 +24,7 @@ H [0-9A-Fa-f]
"//".* count_(); "//".* count_();
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */ [/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */
"enum" { count_(); return ENUM; }
"struct" { count_(); return STRUCT; } "struct" { count_(); return STRUCT; }
{I}({I}|{D})* { yylval.ptr = strnew_(); count_(); return IDENT; } {I}({I}|{D})* { yylval.ptr = strnew_(); count_(); return IDENT; }
@ -31,7 +32,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_();

165
biner.y
View File

@ -24,10 +24,11 @@ extern int yylex(void);
#define yyerror(msg) \ #define yyerror(msg) \
fprintf(stderr, "[%zu:%zu] "msg"\n", ctx.line+1, ctx.column+1) fprintf(stderr, "[%zu:%zu] "msg"\n", ctx.line+1, ctx.column+1)
static inline bool static inline biner_zone_ptr(biner_tree_decl_t)
unstringify_struct_member_type_name_( create_decl_(
biner_tree_struct_member_type_name_t* name, biner_zone_ptr(char) name,
biner_zone_ptr(char) str biner_tree_decl_type_t type,
biner_zone_ptr(void) body
); );
static inline biner_zone_ptr(biner_tree_decl_t) static inline biner_zone_ptr(biner_tree_decl_t)
@ -35,9 +36,21 @@ find_decl_by_name_(
biner_zone_ptr(char) name biner_zone_ptr(char) 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(char) name
);
static inline bool
unstringify_struct_member_type_name_(
biner_tree_struct_member_type_name_t* name,
biner_zone_ptr(char) str
);
static inline biner_zone_ptr(biner_tree_struct_member_t) static inline biner_zone_ptr(biner_tree_struct_member_t)
find_struct_member_by_name_( find_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) last_member, biner_zone_ptr(biner_tree_struct_member_t) tail_member,
biner_zone_ptr(char) name biner_zone_ptr(char) name
); );
@ -70,11 +83,12 @@ resolve_constant_(
uintptr_t ptr; uintptr_t ptr;
} }
%token STRUCT %token ENUM STRUCT
%token <ptr> IDENT %token <ptr> IDENT
%token <i> INTEGER; %token <i> INTEGER;
%type <ptr> decl_list decl %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
%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 add_expr mul_expr operand
@ -98,34 +112,65 @@ decl_list
; ;
decl decl
: STRUCT IDENT '{' struct_member_list '}' ';' { : ENUM IDENT '{' enum_member_list '}' ';' {
if (find_decl_by_name_($2) != 0) { $$ = create_decl_($2, BINER_TREE_DECL_TYPE_ENUM, $4);
yyerrorf("duplicated declaration of '%s'", ref(char, $2)); if ($$ == 0) YYABORT;
}
| ENUM IDENT '{' enum_member_list ',' '}' ';' {
$$ = create_decl_($2, BINER_TREE_DECL_TYPE_ENUM, $4);
if ($$ == 0) YYABORT;
}
| STRUCT IDENT '{' struct_member_list '}' ';' {
$$ = create_decl_($2, BINER_TREE_DECL_TYPE_STRUCT, $4);
if ($$ == 0) YYABORT;
}
;
enum_member_list
: enum_member {
$$ = ctx.last_enum = $1;
}
| enum_member_list ',' enum_member {
ref(biner_tree_enum_member_t, $3)->prev = $1;
$$ = ctx.last_enum = $3;
}
;
enum_member
: IDENT '=' expr {
if (resolve_constant_($1) != 0) {
yyerrorf("duplicated symbol name, '%s'", ref(char, $1));
YYABORT; YYABORT;
} }
$$ = alloc_(biner_tree_decl_t); if (ref(biner_tree_expr_t, $3)->dynamic) {
*ref(biner_tree_decl_t, $$) = (biner_tree_decl_t) { yyerrorf("dynamic expression is not allowed for enum member, '%s'", ref(char, $1));
.name = $2, YYABORT;
.member = $4, }
$$ = alloc_(biner_tree_enum_member_t);
*ref(biner_tree_enum_member_t, $$) = (biner_tree_enum_member_t) {
.name = $1,
.expr = $3,
}; };
ctx.last_decl = $$;
ctx.last_member = 0;
} }
; ;
struct_member_list struct_member_list
: struct_member { : struct_member {
$$ = ctx.last_member = $1; $$ = ctx.last_struct = $1;
} }
| struct_member_list struct_member { | struct_member_list struct_member {
ref(biner_tree_struct_member_t, $2)->prev = $1; ref(biner_tree_struct_member_t, $2)->prev = $1;
$$ = ctx.last_member = $2; $$ = ctx.last_struct = $2;
} }
; ;
struct_member struct_member
: struct_member_type IDENT ';' { : struct_member_type IDENT ';' {
if (find_struct_member_by_name_(ctx.last_member, $2) != 0) { 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)); yyerrorf("duplicated struct member of '%s'", ref(char, $2));
YYABORT; YYABORT;
} }
@ -213,7 +258,7 @@ operand
} }
| IDENT { | IDENT {
const biner_zone_ptr(biner_tree_struct_member_t) m = const biner_zone_ptr(biner_tree_struct_member_t) m =
find_struct_member_by_name_(ctx.last_member, $1); find_struct_member_by_name_(ctx.last_struct, $1);
if (m != 0) { if (m != 0) {
biner_zone_ptr(biner_tree_struct_member_reference_t) mref = biner_zone_ptr(biner_tree_struct_member_reference_t) mref =
alloc_(biner_tree_struct_member_reference_t); alloc_(biner_tree_struct_member_reference_t);
@ -261,17 +306,27 @@ operand
; ;
%% %%
static inline bool unstringify_struct_member_type_name_( static inline biner_zone_ptr(biner_tree_decl_t) create_decl_(
biner_tree_struct_member_type_name_t* name, biner_zone_ptr(char) name,
biner_zone_ptr(char) str) { biner_tree_decl_type_t type,
for (size_t i = 0; i < BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_; ++i) { biner_zone_ptr(void) body) {
const char* item = biner_tree_struct_member_type_name_string_map[i]; if (resolve_constant_(name) != 0) {
if (item != NULL && strcmp(ref(char, str), item) == 0) { yyerrorf("duplicated symbol name, '%s'", ref(char, name));
*name = (biner_tree_struct_member_type_name_t) i; return 0;
return true;
}
} }
return false; if (find_decl_by_name_(name) != 0) {
yyerrorf("duplicated declaration of '%s'", ref(char, name));
return 0;
}
biner_zone_ptr(biner_tree_decl_t) decl = alloc_(biner_tree_decl_t);
*ref(biner_tree_decl_t, decl) = (biner_tree_decl_t) {
.name = name,
.type = type,
.body = body,
};
ctx.last_decl = decl;
ctx.last_body = 0;
return decl;
} }
static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_( static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_(
@ -285,11 +340,38 @@ static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_(
return 0; return 0;
} }
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) {
biner_zone_ptr(biner_tree_enum_member_t) itr = tail_member;
while (itr) {
const biner_tree_enum_member_t* member = ref(biner_tree_enum_member_t, itr);
if (strcmp(ref(char, member->name), ref(char, name)) == 0) {
return member->expr;
}
itr = member->prev;
}
return 0;
}
static inline bool unstringify_struct_member_type_name_(
biner_tree_struct_member_type_name_t* name,
biner_zone_ptr(char) str) {
for (size_t i = 0; i < BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_; ++i) {
const char* item = biner_tree_struct_member_type_name_string_map[i];
if (item != NULL && strcmp(ref(char, str), item) == 0) {
*name = (biner_tree_struct_member_type_name_t) i;
return true;
}
}
return false;
}
static inline biner_zone_ptr(biner_tree_struct_member_t) static inline biner_zone_ptr(biner_tree_struct_member_t)
find_struct_member_by_name_( find_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) last_member, biner_zone_ptr(biner_tree_struct_member_t) tail_member,
biner_zone_ptr(char) name) { biner_zone_ptr(char) name) {
biner_zone_ptr(biner_tree_struct_member_t) itr = last_member; biner_zone_ptr(biner_tree_struct_member_t) itr = tail_member;
while (itr) { while (itr) {
const biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, itr); const biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, itr);
if (strcmp(ref(char, m->name), ref(char, name)) == 0) return itr; if (strcmp(ref(char, m->name), ref(char, name)) == 0) return itr;
@ -317,7 +399,7 @@ find_child_struct_member_by_name_(
ref(char, m->name)); ref(char, m->name));
return 0; return 0;
} }
return find_struct_member_by_name_(d->member, name); return find_struct_member_by_name_(d->struct_, name);
} }
static inline biner_zone_ptr(biner_tree_struct_member_t) static inline biner_zone_ptr(biner_tree_struct_member_t)
@ -346,7 +428,22 @@ static inline biner_zone_ptr(biner_tree_expr_t) create_operator_(
static inline biner_zone_ptr(biner_tree_expr_t) resolve_constant_( static inline biner_zone_ptr(biner_tree_expr_t) resolve_constant_(
biner_zone_ptr(char) ident) { biner_zone_ptr(char) ident) {
(void) ident; biner_zone_ptr(biner_tree_expr_t) expr =
/* TODO: find out enums and constants */ find_enum_member_by_name_(ctx.last_enum, ident);
if (expr != 0) return expr;
biner_zone_ptr(biner_tree_decl_t) itr = ctx.last_decl;
while (itr) {
const biner_tree_decl_t* decl = ref(biner_tree_decl_t, itr);
switch (decl->type) {
case BINER_TREE_DECL_TYPE_ENUM:
expr = find_enum_member_by_name_(decl->enum_, ident);
break;
default:
;
}
if (expr != 0) return expr;
itr = decl->prev;
}
return 0; return 0;
} }

67
main.c
View File

@ -1,9 +1,49 @@
#include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "./tree.h" #include "./tree.h"
static inline void print_enum_(
const uint8_t* zone, const biner_tree_decl_t* decl) {
assert(zone != NULL);
assert(decl != NULL);
printf("enum %s:\n", zone + decl->name);
const biner_tree_enum_member_t* member =
(const biner_tree_enum_member_t*) (zone + decl->enum_);
while ((uintptr_t) member != (uintptr_t) zone) {
printf(" %s\n", zone + member->name);
member = (const biner_tree_enum_member_t*) (zone + member->prev);
}
}
static inline void print_struct_(
const uint8_t* zone, const biner_tree_decl_t* decl) {
assert(zone != NULL);
assert(decl != NULL);
printf("struct %s:\n", zone + decl->name);
const biner_tree_struct_member_t* member =
(const biner_tree_struct_member_t*) (zone + decl->struct_);
while ((uintptr_t) member != (uintptr_t) zone) {
printf(" ");
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) {
const biner_tree_decl_t* decl =
(const biner_tree_decl_t*) (zone + type->decl);
printf("%8s ", zone + decl->name);
} else {
printf("%8s ",
biner_tree_struct_member_type_name_string_map[type->name]);
}
printf("%s\n", zone + member->name);
member = (const biner_tree_struct_member_t*) (zone + member->prev);
}
}
int main(void) { int main(void) {
const uint8_t* zone = biner_tree_parse(stdin); const uint8_t* zone = biner_tree_parse(stdin);
if (zone == NULL) return EXIT_FAILURE; if (zone == NULL) return EXIT_FAILURE;
@ -13,24 +53,15 @@ int main(void) {
const biner_tree_decl_t* decl = const biner_tree_decl_t* decl =
(const biner_tree_decl_t*) (zone + root->decls); (const biner_tree_decl_t*) (zone + root->decls);
while ((uintptr_t) decl != (uintptr_t) zone) { while ((uintptr_t) decl != (uintptr_t) zone) {
printf("%s:\n", zone + decl->name); switch (decl->type) {
case BINER_TREE_DECL_TYPE_ENUM:
const biner_tree_struct_member_t* member = print_enum_(zone, decl);
(const biner_tree_struct_member_t*) (zone + decl->member); break;
while ((uintptr_t) member != (uintptr_t) zone) { case BINER_TREE_DECL_TYPE_STRUCT:
printf(" "); print_struct_(zone, decl);
const biner_tree_struct_member_type_t* type = break;
(const biner_tree_struct_member_type_t*) (zone + member->type); default:
if (type->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { ;
const biner_tree_decl_t* decl =
(const biner_tree_decl_t*) (zone + type->decl);
printf("%8s ", zone + decl->name);
} else {
printf("%8s ",
biner_tree_struct_member_type_name_string_map[type->name]);
}
printf("%s\n", zone + member->name);
member = (const biner_tree_struct_member_t*) (zone + member->prev);
} }
decl = (const biner_tree_decl_t*) (zone + decl->prev); decl = (const biner_tree_decl_t*) (zone + decl->prev);
} }

27
tree.h
View File

@ -13,7 +13,7 @@
typedef struct biner_tree_expr_t biner_tree_expr_t; typedef struct biner_tree_expr_t biner_tree_expr_t;
typedef struct biner_tree_struct_member_t biner_tree_struct_member_t; typedef struct biner_tree_struct_member_t biner_tree_struct_member_t;
typedef struct biner_tree_struct_member_reference_t biner_tree_struct_member_reference_t; typedef struct biner_tree_struct_member_reference_t biner_tree_struct_member_reference_t;
typedef struct biner_tree_struct_t biner_tree_struct_t; typedef struct biner_tree_enum_member_t biner_tree_enum_member_t;
typedef struct biner_tree_decl_t biner_tree_decl_t; typedef struct biner_tree_decl_t biner_tree_decl_t;
typedef enum biner_tree_expr_type_t { typedef enum biner_tree_expr_type_t {
@ -78,7 +78,6 @@ 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_t) owner;
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_struct_member_t) prev; biner_zone_ptr(biner_tree_struct_member_t) prev;
@ -90,15 +89,25 @@ typedef struct biner_tree_struct_member_reference_t {
biner_zone_ptr(biner_tree_struct_member_reference_t) prev; biner_zone_ptr(biner_tree_struct_member_reference_t) prev;
} biner_tree_struct_member_reference_t; } biner_tree_struct_member_reference_t;
typedef struct biner_tree_enum_member_t {
biner_zone_ptr(char) name;
biner_zone_ptr(biner_tree_expr_t) expr;
biner_zone_ptr(biner_tree_enum_member_t) prev;
} biner_tree_enum_member_t;
typedef enum biner_tree_decl_type_t { typedef enum biner_tree_decl_type_t {
BINER_TREE_DECL_TYPE_STRUCT, BINER_TREE_DECL_TYPE_STRUCT,
BINER_TREE_DECL_TYPE_ENUM,
} biner_tree_decl_type_t; } biner_tree_decl_type_t;
typedef struct biner_tree_decl_t { typedef struct biner_tree_decl_t {
biner_zone_ptr(char) name; biner_zone_ptr(char) name;
biner_tree_decl_type_t type; biner_tree_decl_type_t type;
union { union {
biner_zone_ptr(biner_tree_struct_member_t) member; biner_zone_ptr(void) body;
biner_zone_ptr(biner_tree_struct_member_t) struct_;
biner_zone_ptr(biner_tree_enum_member_t) enum_;
}; };
biner_zone_ptr(biner_tree_decl_t) prev; biner_zone_ptr(biner_tree_decl_t) prev;
} biner_tree_decl_t; } biner_tree_decl_t;
@ -114,9 +123,15 @@ typedef struct biner_tree_parse_context_t {
size_t line; size_t line;
size_t column; size_t column;
biner_zone_ptr(biner_tree_root_t) root; biner_zone_ptr(biner_tree_root_t) root;
biner_zone_ptr(biner_tree_decl_t) last_decl; biner_zone_ptr(biner_tree_decl_t) last_decl;
biner_zone_ptr(biner_tree_struct_member_t) last_member;
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; } biner_tree_parse_context_t;
extern biner_tree_parse_context_t biner_tree_parse_context_; extern biner_tree_parse_context_t biner_tree_parse_context_;