Finshed up the regex backend
This commit is contained in:
parent
204147a3d2
commit
13088c9d7a
39 changed files with 481 additions and 250 deletions
|
|
@ -41,11 +41,11 @@ static const HParserVtable action_vt = {
|
|||
.compile_to_rvm = action_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_action(const HParser* p, const HAction a) {
|
||||
HParser* h_action(const HParser* p, const HAction a) {
|
||||
return h_action__m(&system_allocator, p, a);
|
||||
}
|
||||
|
||||
const HParser* h_action__m(HAllocator* mm__, const HParser* p, const HAction a) {
|
||||
HParser* h_action__m(HAllocator* mm__, const HParser* p, const HAction a) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
res->vtable = &action_vt;
|
||||
HParseAction *env = h_new(HParseAction, 1);
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ static const HParserVtable and_vt = {
|
|||
};
|
||||
|
||||
|
||||
const HParser* h_and(const HParser* p) {
|
||||
HParser* h_and(const HParser* p) {
|
||||
return h_and__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_and__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_and__m(HAllocator* mm__, const HParser* p) {
|
||||
// zero-width postive lookahead
|
||||
HParser *res = h_new(HParser, 1);
|
||||
res->env = (void*)p;
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ static const HParserVtable attr_bool_vt = {
|
|||
};
|
||||
|
||||
|
||||
const HParser* h_attr_bool(const HParser* p, HPredicate pred) {
|
||||
HParser* h_attr_bool(const HParser* p, HPredicate pred) {
|
||||
return h_attr_bool__m(&system_allocator, p, pred);
|
||||
}
|
||||
const HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred) {
|
||||
HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
res->vtable = &attr_bool_vt;
|
||||
HAttrBool *env = h_new(HAttrBool, 1);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <assert.h>
|
||||
#include "parser_internal.h"
|
||||
|
||||
struct bits_env {
|
||||
|
|
@ -16,6 +17,19 @@ static HParseResult* parse_bits(void* env, HParseState *state) {
|
|||
return make_result(state, result);
|
||||
}
|
||||
|
||||
static bool h_svm_action_bits(HArena *arena, HSVMContext *ctx, void* env) {
|
||||
// BUG: relies un undefined behaviour: int64_t is a signed uint64_t; not necessarily true on 32-bit
|
||||
struct bits_env *env_ = env;
|
||||
HParsedToken *top = ctx->stack[ctx->stack_count-1];
|
||||
assert(top->token_type == TT_BYTES);
|
||||
uint64_t res = 0;
|
||||
for (size_t i = 0; i < top->bytes.len; i++)
|
||||
res = (res << 8) | top->bytes.token[i]; // TODO: Handle other endiannesses.
|
||||
top->uint = res; // possibly cast to signed through union
|
||||
top->token_type = (env_->signedp ? TT_SINT : TT_UINT);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bits_ctrvm(HRVMProg *prog, void* env) {
|
||||
struct bits_env *env_ = (struct bits_env*)env;
|
||||
h_rvm_insert_insn(prog, RVM_PUSH, 0);
|
||||
|
|
@ -24,6 +38,7 @@ static bool bits_ctrvm(HRVMProg *prog, void* env) {
|
|||
h_rvm_insert_insn(prog, RVM_STEP, 0);
|
||||
}
|
||||
h_rvm_insert_insn(prog, RVM_CAPTURE, 0);
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_bits, env));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -34,10 +49,10 @@ static const HParserVtable bits_vt = {
|
|||
.compile_to_rvm = bits_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_bits(size_t len, bool sign) {
|
||||
HParser* h_bits(size_t len, bool sign) {
|
||||
return h_bits__m(&system_allocator, len, sign);
|
||||
}
|
||||
const HParser* h_bits__m(HAllocator* mm__, size_t len, bool sign) {
|
||||
HParser* h_bits__m(HAllocator* mm__, size_t len, bool sign) {
|
||||
struct bits_env *env = h_new(struct bits_env, 1);
|
||||
env->length = len;
|
||||
env->signedp = sign;
|
||||
|
|
@ -48,10 +63,10 @@ const HParser* h_bits__m(HAllocator* mm__, size_t len, bool sign) {
|
|||
}
|
||||
|
||||
#define SIZED_BITS(name_pre, len, signedp) \
|
||||
const HParser* h_##name_pre##len () { \
|
||||
HParser* h_##name_pre##len () { \
|
||||
return h_bits__m(&system_allocator, len, signedp); \
|
||||
} \
|
||||
const HParser* h_##name_pre##len##__m(HAllocator* mm__) { \
|
||||
HParser* h_##name_pre##len##__m(HAllocator* mm__) { \
|
||||
return h_bits__m(mm__, len, signedp); \
|
||||
}
|
||||
SIZED_BITS(int, 8, true)
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ static const HParserVtable butnot_vt = {
|
|||
.compile_to_rvm = h_not_regular,
|
||||
};
|
||||
|
||||
const HParser* h_butnot(const HParser* p1, const HParser* p2) {
|
||||
HParser* h_butnot(const HParser* p1, const HParser* p2) {
|
||||
return h_butnot__m(&system_allocator, p1, p2);
|
||||
}
|
||||
const HParser* h_butnot__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HParser* h_butnot__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HTwoParsers *env = h_new(HTwoParsers, 1);
|
||||
env->p1 = p1; env->p2 = p2;
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ static HParseResult* parse_ch(void* env, HParseState *state) {
|
|||
|
||||
static bool ch_ctrvm(HRVMProg *prog, void* env) {
|
||||
uint8_t c = (uint8_t)(unsigned long)(env);
|
||||
// TODO: Does this capture anything?
|
||||
h_rvm_insert_insn(prog, RVM_MATCH, c & c << 8);
|
||||
h_rvm_insert_insn(prog, RVM_STEP, 0);
|
||||
return true;
|
||||
|
|
@ -26,12 +27,12 @@ static const HParserVtable ch_vt = {
|
|||
.compile_to_rvm = ch_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_ch(const uint8_t c) {
|
||||
HParser* h_ch(const uint8_t c) {
|
||||
return h_ch__m(&system_allocator, c);
|
||||
}
|
||||
const HParser* h_ch__m(HAllocator* mm__, const uint8_t c) {
|
||||
HParser* h_ch__m(HAllocator* mm__, const uint8_t c) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
ret->vtable = &ch_vt;
|
||||
ret->env = (void*)(unsigned long)(c);
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,21 +59,21 @@ static const HParserVtable charset_vt = {
|
|||
.compile_to_rvm = cs_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_ch_range(const uint8_t lower, const uint8_t upper) {
|
||||
HParser* h_ch_range(const uint8_t lower, const uint8_t upper) {
|
||||
return h_ch_range__m(&system_allocator, lower, upper);
|
||||
}
|
||||
const HParser* h_ch_range__m(HAllocator* mm__, const uint8_t lower, const uint8_t upper) {
|
||||
HParser* h_ch_range__m(HAllocator* mm__, const uint8_t lower, const uint8_t upper) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
HCharset cs = new_charset(mm__);
|
||||
for (int i = 0; i < 256; i++)
|
||||
charset_set(cs, i, (lower <= i) && (i <= upper));
|
||||
ret->vtable = &charset_vt;
|
||||
ret->env = (void*)cs;
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const HParser* h_in_or_not__m(HAllocator* mm__, const uint8_t *options, size_t count, int val) {
|
||||
static HParser* h_in_or_not__m(HAllocator* mm__, const uint8_t *options, size_t count, int val) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
HCharset cs = new_charset(mm__);
|
||||
for (size_t i = 0; i < 256; i++)
|
||||
|
|
@ -83,22 +83,22 @@ static const HParser* h_in_or_not__m(HAllocator* mm__, const uint8_t *options, s
|
|||
|
||||
ret->vtable = &charset_vt;
|
||||
ret->env = (void*)cs;
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_in(const uint8_t *options, size_t count) {
|
||||
HParser* h_in(const uint8_t *options, size_t count) {
|
||||
return h_in_or_not__m(&system_allocator, options, count, 1);
|
||||
}
|
||||
|
||||
const HParser* h_in__m(HAllocator* mm__, const uint8_t *options, size_t count) {
|
||||
HParser* h_in__m(HAllocator* mm__, const uint8_t *options, size_t count) {
|
||||
return h_in_or_not__m(mm__, options, count, 1);
|
||||
}
|
||||
|
||||
const HParser* h_not_in(const uint8_t *options, size_t count) {
|
||||
HParser* h_not_in(const uint8_t *options, size_t count) {
|
||||
return h_in_or_not__m(&system_allocator, options, count, 0);
|
||||
}
|
||||
|
||||
const HParser* h_not_in__m(HAllocator* mm__, const uint8_t *options, size_t count) {
|
||||
HParser* h_not_in__m(HAllocator* mm__, const uint8_t *options, size_t count) {
|
||||
return h_in_or_not__m(mm__, options, count, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,27 +64,27 @@ static const HParserVtable choice_vt = {
|
|||
.compile_to_rvm = choice_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_choice(const HParser* p, ...) {
|
||||
HParser* h_choice(const HParser* p, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, p);
|
||||
const HParser* ret = h_choice__mv(&system_allocator, p, ap);
|
||||
HParser* ret = h_choice__mv(&system_allocator, p, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_choice__m(HAllocator* mm__, const HParser* p, ...) {
|
||||
HParser* h_choice__m(HAllocator* mm__, const HParser* p, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, p);
|
||||
const HParser* ret = h_choice__mv(mm__, p, ap);
|
||||
HParser* ret = h_choice__mv(mm__, p, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_choice__v(const HParser* p, va_list ap) {
|
||||
HParser* h_choice__v(const HParser* p, va_list ap) {
|
||||
return h_choice__mv(&system_allocator, p, ap);
|
||||
}
|
||||
|
||||
const HParser* h_choice__mv(HAllocator* mm__, const HParser* p, va_list ap_) {
|
||||
HParser* h_choice__mv(HAllocator* mm__, const HParser* p, va_list ap_) {
|
||||
va_list ap;
|
||||
size_t len = 0;
|
||||
HSequence *s = h_new(HSequence, 1);
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ static HParserVtable difference_vt = {
|
|||
.compile_to_rvm = h_not_regular,
|
||||
};
|
||||
|
||||
const HParser* h_difference(const HParser* p1, const HParser* p2) {
|
||||
HParser* h_difference(const HParser* p1, const HParser* p2) {
|
||||
return h_difference__m(&system_allocator, p1, p2);
|
||||
}
|
||||
const HParser* h_difference__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HParser* h_difference__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HTwoParsers *env = h_new(HTwoParsers, 1);
|
||||
env->p1 = p1; env->p2 = p2;
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ static const HParserVtable end_vt = {
|
|||
.compile_to_rvm = end_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_end_p() {
|
||||
HParser* h_end_p() {
|
||||
return h_end_p__m(&system_allocator);
|
||||
}
|
||||
|
||||
const HParser* h_end_p__m(HAllocator* mm__) {
|
||||
HParser* h_end_p__m(HAllocator* mm__) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
ret->vtable = &end_vt;
|
||||
ret->env = NULL;
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@ static const HParser epsilon_p = {
|
|||
.env = NULL
|
||||
};
|
||||
|
||||
const HParser* h_epsilon_p() {
|
||||
return &epsilon_p;
|
||||
HParser* h_epsilon_p() {
|
||||
return h_epsilon_p__m(&system_allocator);
|
||||
}
|
||||
const HParser* h_epsilon_p__m(HAllocator* mm__) {
|
||||
return &epsilon_p;
|
||||
HParser* h_epsilon_p__m(HAllocator* mm__) {
|
||||
HParser *epsilon_p = h_new(HParser, 1);
|
||||
epsilon_p->vtable = &epsilon_vt;
|
||||
return epsilon_p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <assert.h>
|
||||
#include "parser_internal.h"
|
||||
#include "backends/regex_actions.h"
|
||||
|
||||
static HParseResult* parse_ignore(void* env, HParseState* state) {
|
||||
HParseResult *res0 = h_do_parse((HParser*)env, state);
|
||||
|
|
@ -21,10 +21,16 @@ static bool ignore_isValidCF(void *env) {
|
|||
return (p->vtable->isValidCF(p->env));
|
||||
}
|
||||
|
||||
static bool h_svm_action_pop(HArena *arena, HSVMContext *ctx, void* arg) {
|
||||
assert(ctx->stack_count > 0);
|
||||
ctx->stack_count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ignore_ctrvm(HRVMProg *prog, void *env) {
|
||||
HParser *p = (HParser*)env;
|
||||
h_compile_regex(prog, p->env);
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_pop));
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_pop, NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -35,10 +41,10 @@ static const HParserVtable ignore_vt = {
|
|||
.compile_to_rvm = ignore_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_ignore(const HParser* p) {
|
||||
HParser* h_ignore(const HParser* p) {
|
||||
return h_ignore__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_ignore__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_ignore__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* ret = h_new(HParser, 1);
|
||||
ret->vtable = &ignore_vt;
|
||||
ret->env = (void*)p;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <assert.h>
|
||||
#include "parser_internal.h"
|
||||
|
||||
|
||||
|
|
@ -49,14 +50,16 @@ static bool h_svm_action_ignoreseq(HArena *arena, HSVMContext *ctx, void* env) {
|
|||
HParsedToken* save;
|
||||
// We can assume that each subitem generated at most one item on the
|
||||
// stack.
|
||||
assert(seq->len >= 1);
|
||||
for (int i = seq->len - 1; i>=0; i--) {
|
||||
if (i == seq->which && ctx->stack[ctx->stack_count]->token_type != TT_MARK)
|
||||
if (i == (int)seq->which && ctx->stack[ctx->stack_count]->token_type != TT_MARK)
|
||||
save = ctx->stack[ctx->stack_count-1];
|
||||
// skip over everything up to and including the mark.
|
||||
while (ctx->stack[--ctx->stack_count]->token_type != TT_MARK)
|
||||
;
|
||||
}
|
||||
ctx->stack[ctx->stack_count++] = save;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_ctrvm(HRVMProg *prog, void* env) {
|
||||
|
|
@ -82,7 +85,7 @@ static const HParserVtable ignoreseq_vt = {
|
|||
// API frontends
|
||||
//
|
||||
|
||||
static const HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const HParser* q, size_t which) {
|
||||
static HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const HParser* q, size_t which) {
|
||||
HIgnoreSeq *seq = h_new(HIgnoreSeq, 1);
|
||||
seq->parsers = h_new(const HParser*, 2);
|
||||
seq->parsers[0] = p;
|
||||
|
|
@ -96,25 +99,25 @@ static const HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const H
|
|||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_left(const HParser* p, const HParser* q) {
|
||||
HParser* h_left(const HParser* p, const HParser* q) {
|
||||
return h_leftright__m(&system_allocator, p, q, 0);
|
||||
}
|
||||
const HParser* h_left__m(HAllocator* mm__, const HParser* p, const HParser* q) {
|
||||
HParser* h_left__m(HAllocator* mm__, const HParser* p, const HParser* q) {
|
||||
return h_leftright__m(mm__, p, q, 0);
|
||||
}
|
||||
|
||||
const HParser* h_right(const HParser* p, const HParser* q) {
|
||||
HParser* h_right(const HParser* p, const HParser* q) {
|
||||
return h_leftright__m(&system_allocator, p, q, 1);
|
||||
}
|
||||
const HParser* h_right__m(HAllocator* mm__, const HParser* p, const HParser* q) {
|
||||
HParser* h_right__m(HAllocator* mm__, const HParser* p, const HParser* q) {
|
||||
return h_leftright__m(mm__, p, q, 1);
|
||||
}
|
||||
|
||||
|
||||
const HParser* h_middle(const HParser* p, const HParser* x, const HParser* q) {
|
||||
HParser* h_middle(const HParser* p, const HParser* x, const HParser* q) {
|
||||
return h_middle__m(&system_allocator, p, x, q);
|
||||
}
|
||||
const HParser* h_middle__m(HAllocator* mm__, const HParser* p, const HParser* x, const HParser* q) {
|
||||
HParser* h_middle__m(HAllocator* mm__, const HParser* p, const HParser* x, const HParser* q) {
|
||||
HIgnoreSeq *seq = h_new(HIgnoreSeq, 1);
|
||||
seq->parsers = h_new(const HParser*, 3);
|
||||
seq->parsers[0] = p;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ static HParseResult* parse_int_range(void *env, HParseState *state) {
|
|||
}
|
||||
|
||||
bool h_svm_action_validate_int_range(HArena *arena, HSVMContext *ctx, void* env) {
|
||||
HRange *r_env = (*HRange)env;
|
||||
HRange *r_env = (HRange*)env;
|
||||
HParsedToken *head = ctx->stack[ctx->stack_count-1];
|
||||
switch (head-> token_type) {
|
||||
case TT_SINT:
|
||||
|
|
@ -41,7 +41,7 @@ bool h_svm_action_validate_int_range(HArena *arena, HSVMContext *ctx, void* env)
|
|||
}
|
||||
}
|
||||
static bool ir_ctrvm(HRVMProg *prog, void *env) {
|
||||
HRange *r_env = (*HRange)env;
|
||||
HRange *r_env = (HRange*)env;
|
||||
|
||||
h_compile_regex(prog, r_env->p);
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_validate_int_range, env));
|
||||
|
|
@ -55,10 +55,10 @@ static const HParserVtable int_range_vt = {
|
|||
.compile_to_rvm = ir_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper) {
|
||||
HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper) {
|
||||
return h_int_range__m(&system_allocator, p, lower, upper);
|
||||
}
|
||||
const HParser* h_int_range__m(HAllocator* mm__, const HParser *p, const int64_t lower, const int64_t upper) {
|
||||
HParser* h_int_range__m(HAllocator* mm__, const HParser *p, const int64_t lower, const int64_t upper) {
|
||||
// p must be an integer parser, which means it's using parse_bits
|
||||
// TODO: re-add this check
|
||||
//assert_message(p->vtable == &bits_vt, "int_range requires an integer parser");
|
||||
|
|
|
|||
|
|
@ -61,16 +61,20 @@ static bool many_ctrvm(HRVMProg *prog, void *env) {
|
|||
// FIXME: Implement clear_to_mark
|
||||
uint16_t clear_to_mark = h_rvm_create_action(prog, h_svm_action_clear_to_mark, NULL);
|
||||
h_rvm_insert_insn(prog, RVM_PUSH, 0);
|
||||
// TODO: implement min and max properly. Right now, it's always min==0, max==inf
|
||||
uint16_t insn = h_rvm_insert_insn(prog, RVM_FORK, 0);
|
||||
if (!h_compile_regex(prog, repeat->p))
|
||||
return false;
|
||||
if (!h_compile_regex(prog, repeat->sep))
|
||||
return false;
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, clear_to_mark);
|
||||
if (repeat->sep != NULL) {
|
||||
h_rvm_insert_insn(prog, RVM_PUSH, 0);
|
||||
if (!h_compile_regex(prog, repeat->sep))
|
||||
return false;
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, clear_to_mark);
|
||||
}
|
||||
h_rvm_insert_insn(prog, RVM_GOTO, insn);
|
||||
h_rvm_patch_arg(prog, insn, h_rvm_get_ip(prog));
|
||||
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_svm_action_make_sequence, NULL);
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_make_sequence, NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -81,10 +85,10 @@ static const HParserVtable many_vt = {
|
|||
.compile_to_rvm = many_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_many(const HParser* p) {
|
||||
HParser* h_many(const HParser* p) {
|
||||
return h_many__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_many__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_many__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
HRepeat *env = h_new(HRepeat, 1);
|
||||
env->p = p;
|
||||
|
|
@ -96,10 +100,10 @@ const HParser* h_many__m(HAllocator* mm__, const HParser* p) {
|
|||
return res;
|
||||
}
|
||||
|
||||
const HParser* h_many1(const HParser* p) {
|
||||
HParser* h_many1(const HParser* p) {
|
||||
return h_many1__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_many1__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_many1__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
HRepeat *env = h_new(HRepeat, 1);
|
||||
env->p = p;
|
||||
|
|
@ -111,10 +115,10 @@ const HParser* h_many1__m(HAllocator* mm__, const HParser* p) {
|
|||
return res;
|
||||
}
|
||||
|
||||
const HParser* h_repeat_n(const HParser* p, const size_t n) {
|
||||
HParser* h_repeat_n(const HParser* p, const size_t n) {
|
||||
return h_repeat_n__m(&system_allocator, p, n);
|
||||
}
|
||||
const HParser* h_repeat_n__m(HAllocator* mm__, const HParser* p, const size_t n) {
|
||||
HParser* h_repeat_n__m(HAllocator* mm__, const HParser* p, const size_t n) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
HRepeat *env = h_new(HRepeat, 1);
|
||||
env->p = p;
|
||||
|
|
@ -126,10 +130,10 @@ const HParser* h_repeat_n__m(HAllocator* mm__, const HParser* p, const size_t n)
|
|||
return res;
|
||||
}
|
||||
|
||||
const HParser* h_sepBy(const HParser* p, const HParser* sep) {
|
||||
HParser* h_sepBy(const HParser* p, const HParser* sep) {
|
||||
return h_sepBy__m(&system_allocator, p, sep);
|
||||
}
|
||||
const HParser* h_sepBy__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
|
||||
HParser* h_sepBy__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
HRepeat *env = h_new(HRepeat, 1);
|
||||
env->p = p;
|
||||
|
|
@ -141,10 +145,10 @@ const HParser* h_sepBy__m(HAllocator* mm__, const HParser* p, const HParser* sep
|
|||
return res;
|
||||
}
|
||||
|
||||
const HParser* h_sepBy1(const HParser* p, const HParser* sep) {
|
||||
HParser* h_sepBy1(const HParser* p, const HParser* sep) {
|
||||
return h_sepBy1__m(&system_allocator, p, sep);
|
||||
}
|
||||
const HParser* h_sepBy1__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
|
||||
HParser* h_sepBy1__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
HRepeat *env = h_new(HRepeat, 1);
|
||||
env->p = p;
|
||||
|
|
@ -184,10 +188,10 @@ static const HParserVtable length_value_vt = {
|
|||
.isValidCF = h_false,
|
||||
};
|
||||
|
||||
const HParser* h_length_value(const HParser* length, const HParser* value) {
|
||||
HParser* h_length_value(const HParser* length, const HParser* value) {
|
||||
return h_length_value__m(&system_allocator, length, value);
|
||||
}
|
||||
const HParser* h_length_value__m(HAllocator* mm__, const HParser* length, const HParser* value) {
|
||||
HParser* h_length_value__m(HAllocator* mm__, const HParser* length, const HParser* value) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
res->vtable = &length_value_vt;
|
||||
HLenVal *env = h_new(HLenVal, 1);
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ static const HParserVtable not_vt = {
|
|||
.parse = parse_not,
|
||||
.isValidRegular = h_false, /* see and.c for why */
|
||||
.isValidCF = h_false, /* also see and.c for why */
|
||||
.compile_to_rvm = h_not_regular,
|
||||
.compile_to_rvm = h_not_regular, // Is actually regular, but the generation step is currently unable to handle it. TODO: fix this.
|
||||
};
|
||||
|
||||
const HParser* h_not(const HParser* p) {
|
||||
HParser* h_not(const HParser* p) {
|
||||
return h_not__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_not__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_not__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser *res = h_new(HParser, 1);
|
||||
res->vtable = ¬_vt;
|
||||
res->env = (void*)p;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ static HParseResult* parse_nothing() {
|
|||
}
|
||||
|
||||
static bool nothing_ctrvm(HRVMProg *prog, void* env) {
|
||||
h_rvm_insert_insn(prog, RVM_MATCH, 0x00FF);
|
||||
h_rvm_insert_insn(prog, RVM_MATCH, 0x0000);
|
||||
h_rvm_insert_insn(prog, RVM_MATCH, 0xFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -17,11 +18,11 @@ static const HParserVtable nothing_vt = {
|
|||
.compile_to_rvm = nothing_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_nothing_p() {
|
||||
HParser* h_nothing_p() {
|
||||
return h_nothing_p__m(&system_allocator);
|
||||
}
|
||||
const HParser* h_nothing_p__m(HAllocator* mm__) {
|
||||
HParser* h_nothing_p__m(HAllocator* mm__) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
ret->vtable = ¬hing_vt; ret->env = NULL;
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <assert.h>
|
||||
#include "parser_internal.h"
|
||||
|
||||
static HParseResult* parse_optional(void* env, HParseState* state) {
|
||||
|
|
@ -21,12 +22,25 @@ static bool opt_isValidCF(void *env) {
|
|||
return p->vtable->isValidCF(p->env);
|
||||
}
|
||||
|
||||
static bool h_svm_action_optional(HArena *arena, HSVMContext *ctx, void *env) {
|
||||
if (ctx->stack[ctx->stack_count-1]->token_type == TT_MARK) {
|
||||
ctx->stack[ctx->stack_count-1]->token_type = TT_NONE;
|
||||
} else {
|
||||
ctx->stack_count--;
|
||||
assert(ctx->stack[ctx->stack_count-1]->token_type == TT_MARK);
|
||||
ctx->stack[ctx->stack_count-1] = ctx->stack[ctx->stack_count];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool opt_ctrvm(HRVMProg *prog, void* env) {
|
||||
h_rvm_insert_insn(prog, RVM_PUSH, 0);
|
||||
uint16_t insn = h_rvm_insert_insn(prog, RVM_FORK, 0);
|
||||
HParser *p = (HParser*) env;
|
||||
if (!h_compile_regex(prog, p->env))
|
||||
return false;
|
||||
h_rvm_patch_arg(prog, insn, h_rvm_get_ip(prog));
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_optional, NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -37,10 +51,10 @@ static const HParserVtable optional_vt = {
|
|||
.compile_to_rvm = opt_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_optional(const HParser* p) {
|
||||
HParser* h_optional(const HParser* p) {
|
||||
return h_optional__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_optional__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_optional__m(HAllocator* mm__, const HParser* p) {
|
||||
// TODO: re-add this
|
||||
//assert_message(p->vtable != &ignore_vt, "Thou shalt ignore an option, rather than the other way 'round.");
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ static bool sequence_isValidCF(void *env) {
|
|||
|
||||
static bool sequence_ctrvm(HRVMProg *prog, void *env) {
|
||||
HSequence *s = (HSequence*)env;
|
||||
h_rvm_insert_insn(prog, RVM_PUSH, 0);
|
||||
for (size_t i=0; i<s->len; ++i) {
|
||||
if (!s->p_array[i]->vtable->compile_to_rvm(prog, s->p_array[i]->env))
|
||||
return false;
|
||||
}
|
||||
h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_make_sequence, NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -58,27 +60,27 @@ static const HParserVtable sequence_vt = {
|
|||
.compile_to_rvm = sequence_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_sequence(const HParser* p, ...) {
|
||||
HParser* h_sequence(const HParser* p, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, p);
|
||||
const HParser* ret = h_sequence__mv(&system_allocator, p, ap);
|
||||
HParser* ret = h_sequence__mv(&system_allocator, p, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_sequence__m(HAllocator* mm__, const HParser* p, ...) {
|
||||
HParser* h_sequence__m(HAllocator* mm__, const HParser* p, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, p);
|
||||
const HParser* ret = h_sequence__mv(mm__, p, ap);
|
||||
HParser* ret = h_sequence__mv(mm__, p, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const HParser* h_sequence__v(const HParser* p, va_list ap) {
|
||||
HParser* h_sequence__v(const HParser* p, va_list ap) {
|
||||
return h_sequence__mv(&system_allocator, p, ap);
|
||||
}
|
||||
|
||||
const HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) {
|
||||
HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) {
|
||||
va_list ap;
|
||||
size_t len = 0;
|
||||
const HParser *arg;
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ const HParserVtable token_vt = {
|
|||
.compile_to_rvm = token_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_token(const uint8_t *str, const size_t len) {
|
||||
HParser* h_token(const uint8_t *str, const size_t len) {
|
||||
return h_token__m(&system_allocator, str, len);
|
||||
}
|
||||
const HParser* h_token__m(HAllocator* mm__, const uint8_t *str, const size_t len) {
|
||||
HParser* h_token__m(HAllocator* mm__, const uint8_t *str, const size_t len) {
|
||||
HToken *t = h_new(HToken, 1);
|
||||
t->str = (uint8_t*)str, t->len = len;
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
ret->vtable = &token_vt;
|
||||
ret->env = t;
|
||||
return (const HParser*)ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,16 @@ static bool ws_isValidCF(void *env) {
|
|||
|
||||
static bool ws_ctrvm(HRVMProg *prog, void *env) {
|
||||
HParser *p = (HParser*)env;
|
||||
uint16_t start = h_rvm_get_ip(prog);
|
||||
uint16_t next;
|
||||
const char SPACE_CHRS[6] = {' ', '\f', '\n', '\r', '\t', '\v'};
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
next = h_rvm_insert_insn(prog, RVM_FORK, 0);
|
||||
h_rvm_insert_insn(prog, RVM_MATCH, (SPACE_CHRS[i] << 8) | (SPACE_CHRS[i]));
|
||||
h_rvm_insert_insn(prog, RVM_GOTO, start);
|
||||
h_rvm_patch_arg(prog, next, h_rvm_get_ip(prog));
|
||||
}
|
||||
return h_compile_regex(prog, p->env);
|
||||
}
|
||||
|
||||
|
|
@ -36,10 +46,10 @@ static const HParserVtable whitespace_vt = {
|
|||
.compile_to_rvm = ws_ctrvm,
|
||||
};
|
||||
|
||||
const HParser* h_whitespace(const HParser* p) {
|
||||
HParser* h_whitespace(const HParser* p) {
|
||||
return h_whitespace__m(&system_allocator, p);
|
||||
}
|
||||
const HParser* h_whitespace__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser* h_whitespace__m(HAllocator* mm__, const HParser* p) {
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
ret->vtable = &whitespace_vt;
|
||||
ret->env = (void*)p;
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@ static const HParserVtable xor_vt = {
|
|||
.compile_to_rvm = h_not_regular,
|
||||
};
|
||||
|
||||
const HParser* h_xor(const HParser* p1, const HParser* p2) {
|
||||
HParser* h_xor(const HParser* p1, const HParser* p2) {
|
||||
return h_xor__m(&system_allocator, p1, p2);
|
||||
}
|
||||
const HParser* h_xor__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HParser* h_xor__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
|
||||
HTwoParsers *env = h_new(HTwoParsers, 1);
|
||||
env->p1 = p1; env->p2 = p2;
|
||||
HParser *ret = h_new(HParser, 1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue