2015-01-23 18:59:30 +01:00
|
|
|
#include "parser_internal.h"
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const HParser *p;
|
|
|
|
|
HContinuation k;
|
|
|
|
|
void *env;
|
2015-02-23 14:10:29 +01:00
|
|
|
HAllocator *mm__;
|
2015-01-23 18:59:30 +01:00
|
|
|
} BindEnv;
|
|
|
|
|
|
2015-02-23 14:10:29 +01:00
|
|
|
// an HAllocator backed by an HArena
|
|
|
|
|
typedef struct {
|
|
|
|
|
HAllocator allocator; // inherit XXX is this the proper way to do it?
|
|
|
|
|
HArena *arena;
|
|
|
|
|
} ArenaAllocator;
|
|
|
|
|
|
2015-03-04 14:52:28 +01:00
|
|
|
static void *aa_alloc(HAllocator *allocator, size_t size)
|
2015-02-23 14:10:29 +01:00
|
|
|
{
|
|
|
|
|
HArena *arena = ((ArenaAllocator *)allocator)->arena;
|
|
|
|
|
return h_arena_malloc(arena, size);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 14:52:28 +01:00
|
|
|
static void *aa_realloc(HAllocator *allocator, void *ptr, size_t size)
|
2015-02-23 14:10:29 +01:00
|
|
|
{
|
|
|
|
|
HArena *arena = ((ArenaAllocator *)allocator)->arena;
|
|
|
|
|
assert(0); // XXX realloc for arena allocator
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 14:52:28 +01:00
|
|
|
static void aa_free(HAllocator *allocator, void *ptr)
|
2015-02-23 14:10:29 +01:00
|
|
|
{
|
|
|
|
|
HArena *arena = ((ArenaAllocator *)allocator)->arena;
|
|
|
|
|
h_arena_free(arena, ptr);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-23 18:59:30 +01:00
|
|
|
static HParseResult *parse_bind(void *be_, HParseState *state) {
|
|
|
|
|
BindEnv *be = be_;
|
|
|
|
|
|
|
|
|
|
HParseResult *res = h_do_parse(be->p, state);
|
|
|
|
|
if(!res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2015-02-23 14:10:29 +01:00
|
|
|
// create a temporary arena allocator for the continuation
|
|
|
|
|
HArena *arena = h_new_arena(be->mm__, 0);
|
|
|
|
|
ArenaAllocator aa = {{aa_alloc, aa_realloc, aa_free}, arena};
|
|
|
|
|
|
|
|
|
|
HParser *kx = be->k((HAllocator *)&aa, res->ast, be->env);
|
|
|
|
|
if(!kx) {
|
|
|
|
|
h_delete_arena(arena);
|
2015-01-23 22:06:43 +01:00
|
|
|
return NULL;
|
2015-02-23 14:10:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = h_do_parse(kx, state);
|
2015-01-23 22:06:43 +01:00
|
|
|
|
2015-02-23 14:10:29 +01:00
|
|
|
h_delete_arena(arena);
|
|
|
|
|
return res;
|
2015-01-23 18:59:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const HParserVtable bind_vt = {
|
|
|
|
|
.parse = parse_bind,
|
|
|
|
|
.isValidRegular = h_false,
|
|
|
|
|
.isValidCF = h_false,
|
|
|
|
|
.compile_to_rvm = h_not_regular,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
HParser *h_bind(const HParser *p, HContinuation k, void *env)
|
|
|
|
|
{
|
|
|
|
|
return h_bind__m(&system_allocator, p, k, env);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HParser *h_bind__m(HAllocator *mm__,
|
|
|
|
|
const HParser *p, HContinuation k, void *env)
|
|
|
|
|
{
|
|
|
|
|
BindEnv *be = h_new(BindEnv, 1);
|
|
|
|
|
|
|
|
|
|
be->p = p;
|
|
|
|
|
be->k = k;
|
|
|
|
|
be->env = env;
|
2015-02-23 14:10:29 +01:00
|
|
|
be->mm__ = mm__;
|
2015-01-23 18:59:30 +01:00
|
|
|
|
|
|
|
|
return h_new_parser(mm__, &bind_vt, be);
|
|
|
|
|
}
|