Implements error handling of parser.
This commit is contained in:
parent
9c751437c6
commit
5f375dff74
5
TODO.TXT
5
TODO.TXT
@ -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
66
biner.l
@ -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;
|
||||
}
|
||||
}
|
||||
|
134
biner.y
134
biner.y
@ -11,26 +11,34 @@
|
||||
|
||||
#define ctx (biner_tree_parse_context_)
|
||||
|
||||
#define alloc_(T) (biner_zone_alloc(&ctx.zone, sizeof(T)))
|
||||
#define alloc_(T) (biner_zone_alloc(&ctx.zone, sizeof(T)))
|
||||
#define ref(T, p) ((T*) (ctx.zone.ptr+p))
|
||||
|
||||
extern int yylex(void);
|
||||
extern void yyerror(const char*);
|
||||
extern char* yytext;
|
||||
|
||||
extern int yylex(void);
|
||||
|
||||
#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) {
|
||||
@ -113,7 +129,7 @@ struct_member_type
|
||||
*ref(biner_tree_struct_member_type_t, $$) =
|
||||
(biner_tree_struct_member_type_t) {
|
||||
.kind = BINER_TREE_STRUCT_MEMBER_TYPE_KIND_GENERIC,
|
||||
.generic = $1,
|
||||
.generic = $1,
|
||||
.qualifier = BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY,
|
||||
.expr = $3,
|
||||
};
|
||||
@ -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
6
tree.c
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user