#include "parser_internal.h" // // general case: parse sequence, pick one result // typedef struct HIgnoreSeq_ { const HParser **parsers; size_t len; // how many parsers in 'ps' size_t which; // whose result to return } HIgnoreSeq; static HParseResult* parse_ignoreseq(void* env, HParseState *state) { const HIgnoreSeq *seq = (HIgnoreSeq*)env; HParseResult *res = NULL; for (size_t i=0; i < seq->len; ++i) { HParseResult *tmp = h_do_parse(seq->parsers[i], state); if (!tmp) return NULL; else if (i == seq->which) res = tmp; } return res; } static bool is_isValidRegular(void *env) { HIgnoreSeq *seq = (HIgnoreSeq*)env; for (size_t i=0; ilen; ++i) { if (!seq->parsers[i]->vtable->isValidRegular(seq->parsers[i]->env)) return false; } return true; } static bool is_isValidCF(void *env) { HIgnoreSeq *seq = (HIgnoreSeq*)env; for (size_t i=0; ilen; ++i) { if (!seq->parsers[i]->vtable->isValidCF(seq->parsers[i]->env)) return false; } return true; } static bool h_svm_action_ignoreseq(HArena *arena, HSVMContext *ctx, void* env) { HIgnoreSeq *seq = (HIgnoreSeq*)env; HParsedToken* save; // We can assume that each subitem generated at most one item on the // stack. for (int i = seq->len - 1; i>=0; i--) { if (i == 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; } static bool is_ctrvm(HRVMProg *prog, void* env) { HIgnoreSeq *seq = (HIgnoreSeq*)env; for (size_t i=0; ilen; ++i) { h_rvm_insert_insn(prog, RVM_PUSH, 0); if (!h_compile_regex(prog, seq->parsers[i]->env)) return false; } h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_ignoreseq, env)); return true; } static const HParserVtable ignoreseq_vt = { .parse = parse_ignoreseq, .isValidRegular = is_isValidRegular, .isValidCF = is_isValidCF, .compile_to_rvm = is_ctrvm, }; // // API frontends // static const 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; seq->parsers[1] = q; seq->len = 2; seq->which = which; HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; } const 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) { return h_leftright__m(mm__, p, q, 0); } const 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) { return h_leftright__m(mm__, p, q, 1); } const 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) { HIgnoreSeq *seq = h_new(HIgnoreSeq, 1); seq->parsers = h_new(const HParser*, 3); seq->parsers[0] = p; seq->parsers[1] = x; seq->parsers[2] = q; seq->len = 3; seq->which = 1; HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; }