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
|
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
|
expression resolving
|
||||||
enum support
|
enum support
|
||||||
union support
|
union support
|
||||||
|
66
biner.l
66
biner.l
@ -1,7 +1,6 @@
|
|||||||
%option noinput nounput noyywrap
|
%option noinput nounput noyywrap
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -11,10 +10,34 @@
|
|||||||
|
|
||||||
#include "generated/biner.y.h"
|
#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) {
|
D [0-9]
|
||||||
return biner_zone_strnew(&ctx.zone, str);
|
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) {
|
static inline intmax_t parse_int_(int base) {
|
||||||
char* end = NULL;
|
char* end = NULL;
|
||||||
@ -27,26 +50,15 @@ static inline intmax_t parse_int_(int base) {
|
|||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
%}
|
static inline void count_(void) {
|
||||||
|
const char* s = yytext;
|
||||||
D [0-9]
|
while (*s) {
|
||||||
I [A-Za-z_]
|
if (*s == '\n') {
|
||||||
H [0-9A-Fa-f]
|
biner_tree_parse_context_.column = 0;
|
||||||
|
++biner_tree_parse_context_.line;
|
||||||
%%
|
} else {
|
||||||
|
++biner_tree_parse_context_.column;
|
||||||
"//".* ;
|
}
|
||||||
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] ; /* TODO: detect unterminated comment */
|
++s;
|
||||||
|
}
|
||||||
"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) ;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
128
biner.y
128
biner.y
@ -14,23 +14,31 @@
|
|||||||
#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))
|
#define ref(T, p) ((T*) (ctx.zone.ptr+p))
|
||||||
|
|
||||||
|
extern char* yytext;
|
||||||
|
|
||||||
extern int yylex(void);
|
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)
|
static inline biner_zone_ptr(biner_tree_struct_member_t)
|
||||||
find_struct_member_(
|
find_struct_member_by_name_(
|
||||||
biner_zone_ptr(biner_tree_struct_member_t) itr,
|
biner_zone_ptr(biner_tree_struct_member_t) last_member,
|
||||||
biner_zone_ptr(char) name) {
|
biner_zone_ptr(char) name);
|
||||||
while (itr) {
|
|
||||||
const biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, itr);
|
static inline biner_zone_ptr(biner_tree_struct_member_t)
|
||||||
if (strcmp(ref(char, m->name), ref(char, name)) == 0) {
|
find_child_struct_member_by_name_(
|
||||||
return itr;
|
biner_zone_ptr(biner_tree_struct_member_t) member,
|
||||||
}
|
biner_zone_ptr(char) name);
|
||||||
itr = m->prev;
|
|
||||||
}
|
static inline biner_zone_ptr(biner_tree_struct_member_t)
|
||||||
yyerror("unknown member");
|
unwrap_struct_member_ref_(
|
||||||
return 0;
|
biner_zone_ptr(biner_tree_struct_member_reference_t) memref);
|
||||||
}
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
@ -66,6 +74,10 @@ decl_list
|
|||||||
|
|
||||||
decl
|
decl
|
||||||
: STRUCT IDENT '{' struct_body '}' ';' {
|
: 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);
|
$$ = alloc_(biner_tree_decl_t);
|
||||||
*ref(biner_tree_decl_t, $$) = (biner_tree_decl_t) {
|
*ref(biner_tree_decl_t, $$) = (biner_tree_decl_t) {
|
||||||
.name = $2,
|
.name = $2,
|
||||||
@ -88,6 +100,10 @@ struct_body
|
|||||||
|
|
||||||
struct_member
|
struct_member
|
||||||
: struct_member_type IDENT ';' {
|
: 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);
|
$$ = alloc_(biner_tree_struct_member_t);
|
||||||
*ref(biner_tree_struct_member_t, $$) =
|
*ref(biner_tree_struct_member_t, $$) =
|
||||||
(biner_tree_struct_member_t) {
|
(biner_tree_struct_member_t) {
|
||||||
@ -180,34 +196,82 @@ operand
|
|||||||
|
|
||||||
struct_member_reference
|
struct_member_reference
|
||||||
: IDENT {
|
: 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);
|
$$ = alloc_(biner_tree_struct_member_reference_t);
|
||||||
*ref(biner_tree_struct_member_reference_t, $$) =
|
*ref(biner_tree_struct_member_reference_t, $$) =
|
||||||
(biner_tree_struct_member_reference_t) {
|
(biner_tree_struct_member_reference_t) { .member = member, };
|
||||||
.member = find_struct_member_(ctx.last_member, $1),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
| struct_member_reference '.' IDENT {
|
| struct_member_reference '.' IDENT {
|
||||||
const biner_tree_struct_member_t* p =
|
const biner_zone_ptr(biner_tree_struct_member_t) member =
|
||||||
ref(biner_tree_struct_member_t, $1);
|
find_child_struct_member_by_name_(unwrap_struct_member_ref_($1), $3);
|
||||||
|
if (member == 0) {
|
||||||
const biner_tree_struct_member_type_t* t =
|
yyerrorf("unknown member '%s'", ref(char, $3));
|
||||||
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");
|
|
||||||
YYABORT;
|
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);
|
$$ = alloc_(biner_tree_struct_member_reference_t);
|
||||||
*ref(biner_tree_struct_member_reference_t, $$) =
|
*ref(biner_tree_struct_member_reference_t, $$) =
|
||||||
(biner_tree_struct_member_reference_t) {
|
(biner_tree_struct_member_reference_t) { .member = member, };
|
||||||
.member = find_struct_member_(d->member, $3),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
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};
|
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) {
|
const uint8_t* biner_tree_parse(FILE* fp) {
|
||||||
if (atomic_flag_test_and_set(&biner_tree_parse_context_.dirty)) {
|
if (atomic_flag_test_and_set(&biner_tree_parse_context_.dirty)) {
|
||||||
fprintf(stderr, "parsing context is dirty now\n");
|
fprintf(stderr, "parsing context is dirty now\n");
|
||||||
|
3
tree.h
3
tree.h
@ -94,6 +94,9 @@ typedef struct biner_tree_parse_context_t {
|
|||||||
atomic_flag dirty;
|
atomic_flag dirty;
|
||||||
biner_zone_t zone;
|
biner_zone_t zone;
|
||||||
|
|
||||||
|
size_t line;
|
||||||
|
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;
|
biner_zone_ptr(biner_tree_struct_member_t) last_member;
|
||||||
|
Loading…
Reference in New Issue
Block a user