Implements error handling of parser.

This commit is contained in:
falsycat 2020-12-22 00:00:00 +00:00
parent 9c751437c6
commit 5f375dff74
5 changed files with 145 additions and 69 deletions

View File

@ -1,5 +1,8 @@
X parser
error handling (compiler message)
X error handling (compiler message)
user-defined type resolving
make enum for generic types
location for each declarations
expression resolving
enum support
union support

66
biner.l
View File

@ -1,7 +1,6 @@
%option noinput nounput noyywrap
%{
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
@ -11,10 +10,34 @@
#include "generated/biner.y.h"
#define ctx (biner_tree_parse_context_)
static inline biner_zone_ptr(char) strnew_(void);
static inline intmax_t parse_int_(int base);
static inline void count_(void);
%}
static inline uintptr_t strnew_(const char* str) {
return biner_zone_strnew(&ctx.zone, str);
D [0-9]
I [A-Za-z_]
H [0-9A-Fa-f]
%%
"//".* count_();
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] count_(); /* TODO: detect unterminated comment */
"struct" { count_(); return STRUCT; }
{I}({I}|{D})* { yylval.ptr = strnew_(); count_(); return IDENT; }
{D}+ { yylval.i = parse_int_(10); count_(); return INTEGER; }
0[xX]{H}+ { yylval.i = parse_int_(16); count_(); return INTEGER; }
[\+\-\*\/\.\(\)[\]\{\}\;] { count_(); return yytext[0]; }
(.|\n) count_();
%%
static inline uintptr_t strnew_(void) {
return biner_zone_strnew(&biner_tree_parse_context_.zone, yytext);
}
static inline intmax_t parse_int_(int base) {
char* end = NULL;
@ -27,26 +50,15 @@ static inline intmax_t parse_int_(int base) {
return v;
}
%}
D [0-9]
I [A-Za-z_]
H [0-9A-Fa-f]
%%
"//".* ;
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] ; /* TODO: detect unterminated comment */
"struct" return STRUCT;
{I}({I}|{D})* { yylval.ptr = strnew_(yytext); return IDENT; }
{D}+ { yylval.i = parse_int_(10); return INTEGER; }
0[xX]{H}+ { yylval.i = parse_int_(16); return INTEGER; }
[\+\-\*\/\.\(\)[\]\{\}\;] return yytext[0];
(.|\n) ;
%%
static inline void count_(void) {
const char* s = yytext;
while (*s) {
if (*s == '\n') {
biner_tree_parse_context_.column = 0;
++biner_tree_parse_context_.line;
} else {
++biner_tree_parse_context_.column;
}
++s;
}
}

128
biner.y
View File

@ -14,23 +14,31 @@
#define alloc_(T) (biner_zone_alloc(&ctx.zone, sizeof(T)))
#define ref(T, p) ((T*) (ctx.zone.ptr+p))
extern char* yytext;
extern int yylex(void);
extern void yyerror(const char*);
#define yyerrorf(fmt, ...) \
fprintf(stderr, "[%zu:%zu] "fmt"\n", ctx.line+1, ctx.column+1, __VA_ARGS__)
#define yyerror(msg) \
fprintf(stderr, "[%zu:%zu] "msg"\n", ctx.line+1, ctx.column+1)
static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_(
biner_zone_ptr(char) name);
static inline biner_zone_ptr(biner_tree_struct_member_t)
find_struct_member_(
biner_zone_ptr(biner_tree_struct_member_t) itr,
biner_zone_ptr(char) name) {
while (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;
}
itr = m->prev;
}
yyerror("unknown member");
return 0;
}
find_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) last_member,
biner_zone_ptr(char) name);
static inline biner_zone_ptr(biner_tree_struct_member_t)
find_child_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) member,
biner_zone_ptr(char) name);
static inline biner_zone_ptr(biner_tree_struct_member_t)
unwrap_struct_member_ref_(
biner_zone_ptr(biner_tree_struct_member_reference_t) memref);
%}
%union {
@ -66,6 +74,10 @@ decl_list
decl
: STRUCT IDENT '{' struct_body '}' ';' {
if (find_decl_by_name_($2) != 0) {
yyerrorf("duplicated declaration of '%s'", ref(char, $2));
YYABORT;
}
$$ = alloc_(biner_tree_decl_t);
*ref(biner_tree_decl_t, $$) = (biner_tree_decl_t) {
.name = $2,
@ -88,6 +100,10 @@ struct_body
struct_member
: struct_member_type IDENT ';' {
if (find_struct_member_by_name_(ctx.last_member, $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) {
@ -180,34 +196,82 @@ operand
struct_member_reference
: IDENT {
const biner_zone_ptr(biner_tree_struct_member_t) member =
find_struct_member_by_name_(ctx.last_member, $1);
if (member == 0) {
yyerrorf("unknown member '%s'", ref(char, $1));
YYABORT;
}
$$ = alloc_(biner_tree_struct_member_reference_t);
*ref(biner_tree_struct_member_reference_t, $$) =
(biner_tree_struct_member_reference_t) {
.member = find_struct_member_(ctx.last_member, $1),
};
(biner_tree_struct_member_reference_t) { .member = member, };
}
| struct_member_reference '.' IDENT {
const biner_tree_struct_member_t* p =
ref(biner_tree_struct_member_t, $1);
const biner_tree_struct_member_type_t* t =
ref(biner_tree_struct_member_type_t, p->type);
if (t->kind != BINER_TREE_STRUCT_MEMBER_TYPE_KIND_USER_DEFINED) {
yyerror("not user-defined data");
const biner_zone_ptr(biner_tree_struct_member_t) member =
find_child_struct_member_by_name_(unwrap_struct_member_ref_($1), $3);
if (member == 0) {
yyerrorf("unknown member '%s'", ref(char, $3));
YYABORT;
}
const biner_tree_decl_t* d = ref(biner_tree_decl_t, t->decl);
if (d->type != BINER_TREE_DECL_TYPE_STRUCT) {
yyerror("not struct");
YYABORT;
}
$$ = alloc_(biner_tree_struct_member_reference_t);
*ref(biner_tree_struct_member_reference_t, $$) =
(biner_tree_struct_member_reference_t) {
.member = find_struct_member_(d->member, $3),
};
(biner_tree_struct_member_reference_t) { .member = member, };
}
;
%%
static inline biner_zone_ptr(biner_tree_decl_t) find_decl_by_name_(
biner_zone_ptr(char) name) {
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);
if (strcmp(ref(char, decl->name), ref(char, name)) == 0) return itr;
itr = decl->prev;
}
return 0;
}
static inline biner_zone_ptr(biner_tree_struct_member_t)
find_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) last_member,
biner_zone_ptr(char) name) {
biner_zone_ptr(biner_tree_struct_member_t) itr = last_member;
while (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;
itr = m->prev;
}
return 0;
}
static inline biner_zone_ptr(biner_tree_struct_member_t)
find_child_struct_member_by_name_(
biner_zone_ptr(biner_tree_struct_member_t) member,
biner_zone_ptr(char) name) {
const biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, member);
const biner_tree_struct_member_type_t* t =
ref(biner_tree_struct_member_type_t, m->type);
if (t->kind != BINER_TREE_STRUCT_MEMBER_TYPE_KIND_USER_DEFINED) {
yyerrorf("typeof '%s' is not user-defined", ref(char, m->name));
return 0;
}
const biner_tree_decl_t* d = ref(biner_tree_decl_t, t->decl);
if (d->type != BINER_TREE_DECL_TYPE_STRUCT) {
yyerrorf("'%s' (typeof '%s') is not struct",
ref(char, d->name),
ref(char, m->name));
return 0;
}
return find_struct_member_by_name_(d->member, name);
}
static inline biner_zone_ptr(biner_tree_struct_member_t)
unwrap_struct_member_ref_(
biner_zone_ptr(biner_tree_struct_member_reference_t) memref) {
const biner_tree_struct_member_reference_t* r =
ref(biner_tree_struct_member_reference_t, memref);
return r->member;
}

6
tree.c
View File

@ -14,12 +14,6 @@
biner_tree_parse_context_t biner_tree_parse_context_ = {0};
int yyerror(char* str) {
extern char* yytext;
fprintf(stderr, "error: %s: %s\n", str, yytext);
return 0;
}
const uint8_t* biner_tree_parse(FILE* fp) {
if (atomic_flag_test_and_set(&biner_tree_parse_context_.dirty)) {
fprintf(stderr, "parsing context is dirty now\n");

3
tree.h
View File

@ -94,6 +94,9 @@ typedef struct biner_tree_parse_context_t {
atomic_flag dirty;
biner_zone_t zone;
size_t line;
size_t column;
biner_zone_ptr(biner_tree_root_t) root;
biner_zone_ptr(biner_tree_decl_t) last_decl;
biner_zone_ptr(biner_tree_struct_member_t) last_member;