static HParseResult* parse_length_value(void *env, HParseState *state) { HLenVal *lv = (HLenVal*)env; HParseResult *len = h_do_parse(lv->length, state); if (!len) return NULL; if (len->ast->token_type != TT_UINT) errx(1, "Length parser must return an unsigned integer"); // TODO: allocate this using public functions HRepeat repeat = { .p = lv->value, .sep = h_epsilon_p(), .count = len->ast->uint, .min_p = false }; return parse_many(&repeat, state); } static const HParserVtable length_value_vt = { .parse = parse_length_value, .isValidRegular = h_false, .isValidCF = h_false, }; const 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 *res = h_new(HParser, 1); res->vtable = &length_value_vt; HLenVal *env = h_new(HLenVal, 1); env->length = length; env->value = value; res->env = (void*)env; return res; }
const HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) { va_list ap; size_t len = 0; const HParser *arg; va_copy(ap, ap_); do { len++; arg = va_arg(ap, const HParser *); } while (arg); va_end(ap); HSequence *s = h_new(HSequence, 1); s->p_array = h_new(const HParser *, len); va_copy(ap, ap_); s->p_array[0] = p; for (size_t i = 1; i < len; i++) { s->p_array[i] = va_arg(ap, const HParser *); } while (arg); va_end(ap); s->len = len; HParser *ret = h_new(HParser, 1); ret->vtable = &sequence_vt; ret->env = (void*)s; return ret; }
const 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; }
HSArray *h_sarray_new(HAllocator *mm__, size_t size) { HSArray *ret = h_new(HSArray, 1); ret->capacity = size; ret->used = 0; ret->nodes = h_new(HSArrayNode, size); // Does not actually need to be initialized. ret->mm__ = mm__; // TODO: Add the valgrind hooks to mark this initialized. return ret; }
const 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); env->p = p; env->action = a; res->env = (void*)env; return res; }
const 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); env->p = p; env->pred = pred; res->env = (void*)env; return res; }
const 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; env->sep = sep; env->count = 0; env->min_p = true; res->vtable = &many_vt; res->env = env; return res; }
const HParser* h_many1__m(HAllocator* mm__, const HParser* p) { HParser *res = h_new(HParser, 1); HRepeat *env = h_new(HRepeat, 1); env->p = p; env->sep = h_epsilon_p__m(mm__); env->count = 1; env->min_p = true; res->vtable = &many_vt; res->env = env; return res; }
const 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; env->sep = h_epsilon_p__m(mm__); env->count = n; env->min_p = false; res->vtable = &many_vt; res->env = env; return res; }
HParser* h_with_endianness__m(HAllocator *mm__, char endianness, const HParser *p) { HParseEndianness *env = h_new(HParseEndianness, 1); env->endianness = endianness; env->p = p; return h_new_parser(mm__, &endianness_vt, env); }
HParser* h_action__m(HAllocator* mm__, const HParser* p, const HAction a, void* user_data) { HParseAction *env = h_new(HParseAction, 1); env->p = p; env->action = a; env->user_data = user_data; return h_new_parser(mm__, &action_vt, env); }
HParser *h_aligned__m(HAllocator *mm__, size_t n) { size_t *pn = h_new(size_t, 1); *pn = n; return h_new_parser(mm__, &aligned_vt, pn); }
const 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"); // and regardless, the bounds need to fit in the parser in question // TODO: check this as well. HRange *r_env = h_new(HRange, 1); r_env->p = p; r_env->lower = lower; r_env->upper = upper; HParser *ret = h_new(HParser, 1); ret->vtable = &int_range_vt; ret->env = (void*)r_env; return ret; }
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; seq->parsers[1] = q; seq->len = 2; seq->which = which; return h_new_parser(mm__, &ignoreseq_vt, seq); }
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; return h_new_parser(mm__, &ignoreseq_vt, seq); }
HParser* h_sequence__ma(HAllocator* mm__, void *args[]) { size_t len = -1; // because do...while const HParser *arg; do { arg=((HParser **)args)[++len]; } while(arg); HSequence *s = h_new(HSequence, 1); s->p_array = h_new(HParser *, len); for (size_t i = 0; i < len; i++) { s->p_array[i] = ((HParser **)args)[i]; } s->len = len; HParser *ret = h_new(HParser, 1); ret->vtable = &sequence_vt; ret->env = (void*)s; return ret; }
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->count = 2; seq->which = which; HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; }
static HCFChoice* desugar_many(HAllocator *mm__, void *env) { HRepeat *repeat = (HRepeat*)env; /* many(A) => Ma -> A Mar -> \epsilon (but not if many1/sepBy1 is used) Mar -> Sep A Mar -> \epsilon */ HCFChoice *ret = h_new(HCFChoice, 1); ret->type = HCF_CHOICE; if (repeat->min_p) ret->seq = h_new(HCFSequence*, 2); /* choice of 1 sequence, A Mar */ else
static HCFChoice* desugar_action(HAllocator *mm__, void *env) { HParseAction *a = (HParseAction*)env; HCFSequence *seq = h_new(HCFSequence, 1); seq->items = h_new(HCFChoice*, 2); seq->items[0] = h_desugar(mm__, a->p); seq->items[1] = NULL; HCFChoice *ret = h_new(HCFChoice, 1); ret->type = HCF_CHOICE; ret->seq = h_new(HCFSequence*, 2); ret->seq[0] = seq; ret->seq[1] = NULL; ret->action = a->action; return ret; }
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->count = 3; seq->which = 1; HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; }
// desugar parser with a fresh start symbol // this guarantees that the start symbol will not occur in any productions HCFChoice *h_desugar_augmented(HAllocator *mm__, HParser *parser) { HCFChoice *augmented = h_new(HCFChoice, 1); HCFStack *stk__ = h_cfstack_new(mm__); stk__->prealloc = augmented; HCFS_BEGIN_CHOICE() { HCFS_BEGIN_SEQ() { HCFS_DESUGAR(parser); } HCFS_END_SEQ(); HCFS_THIS_CHOICE->reshape = h_act_first; } HCFS_END_CHOICE(); h_cfstack_free(mm__, stk__); return augmented; }
HLRTable *h_lrtable_new(HAllocator *mm__, size_t nrows) { HArena *arena = h_new_arena(mm__, 0); // default blocksize assert(arena != NULL); HLRTable *ret = h_new(HLRTable, 1); ret->nrows = nrows; ret->ntmap = h_arena_malloc(arena, nrows * sizeof(HHashTable *)); ret->tmap = h_arena_malloc(arena, nrows * sizeof(HStringMap *)); ret->forall = h_arena_malloc(arena, nrows * sizeof(HLRAction *)); ret->inadeq = h_slist_new(arena); ret->arena = arena; ret->mm__ = mm__; for(size_t i=0; i<nrows; i++) { ret->ntmap[i] = h_hashtable_new(arena, h_eq_symbol, h_hash_symbol); ret->tmap[i] = h_stringmap_new(arena); ret->forall[i] = NULL; } return ret; }
Hash *h_clone(Hash *self, h_clone_ft clone_key, h_clone_ft clone_value) { void *key, *value; HashEntry *he; int i = self->size; Hash *ht_clone; ht_clone = h_new(self->hash_i, self->eq_i, self->free_key_i, self->free_value_i); for (he = self->table; i > 0; he++) { if (he->key && he->key != dummy_key) { /* active entry */ key = clone_key ? clone_key(he->key) : he->key; value = clone_value ? clone_value(he->value) : he->value; h_set(ht_clone, key, value); i--; } } return ht_clone; }
HParser* h_sequence__mv(HAllocator* mm__, HParser *p, va_list ap_) { va_list ap; size_t len = 0; const HParser *arg; va_copy(ap, ap_); do { len++; arg = va_arg(ap, HParser *); } while (arg); va_end(ap); HSequence *s = h_new(HSequence, 1); s->p_array = h_new(HParser *, len); va_copy(ap, ap_); s->p_array[0] = p; for (size_t i = 1; i < len; i++) { s->p_array[i] = va_arg(ap, HParser *); } while (arg); va_end(ap); s->len = len; return h_new_parser(mm__, &sequence_vt, s); }
HBenchmarkResults *h_benchmark__m(HAllocator* mm__, HParser* parser, HParserTestcase* testcases) { // For now, just output the results to stderr HParserTestcase* tc = testcases; HParserBackend backend = PB_MIN; HBenchmarkResults *ret = h_new(HBenchmarkResults, 1); ret->len = PB_MAX-PB_MIN+1; ret->results = h_new(HBackendResults, ret->len); for (backend = PB_MIN; backend <= PB_MAX; backend++) { ret->results[backend].backend = backend; // Step 1: Compile grammar for given parser... if (h_compile(parser, backend, NULL) == -1) { // backend inappropriate for grammar... fprintf(stderr, "Compiling for %s failed\n", HParserBackendNames[backend]); ret->results[backend].compile_success = false; ret->results[backend].n_testcases = 0; ret->results[backend].failed_testcases = 0; ret->results[backend].cases = NULL; continue; } fprintf(stderr, "Compiled for %s\n", HParserBackendNames[backend]); ret->results[backend].compile_success = true; int tc_failed = 0; // Step 1: verify all test cases. ret->results[backend].n_testcases = 0; ret->results[backend].failed_testcases = 0; for (tc = testcases; tc->input != NULL; tc++) { ret->results[backend].n_testcases++; HParseResult *res = h_parse(parser, tc->input, tc->length); char* res_unamb; if (res != NULL) { res_unamb = h_write_result_unamb(res->ast); } else res_unamb = NULL; if ((res_unamb == NULL && tc->output_unambiguous != NULL) || (res_unamb != NULL && strcmp(res_unamb, tc->output_unambiguous) != 0)) { // test case failed... fprintf(stderr, "Parsing with %s failed\n", HParserBackendNames[backend]); // We want to run all testcases, for purposes of generating a // report. (eg, if users are trying to fix a grammar for a // faster backend) tc_failed++; ret->results[backend].failed_testcases++; } h_parse_result_free(res); free(res_unamb); } if (tc_failed > 0) { // Can't use this parser; skip to the next fprintf(stderr, "%s failed testcases; skipping benchmark\n", HParserBackendNames[backend]); continue; } ret->results[backend].cases = h_new(HCaseResult, ret->results[backend].n_testcases); size_t cur_case = 0; for (tc = testcases; tc->input != NULL; tc++) { // The goal is to run each testcase for at least 50ms each // TODO: replace this with a posix timer-based benchmark. (cf. timerfd_create, timer_create, setitimer) int count = 1, cur; struct timespec ts_start, ts_end; int64_t time_diff; do { count *= 2; // Yes, this means that the first run will run the function twice. This is fine, as we want multiple runs anyway. h_benchmark_clock_gettime(&ts_start); for (cur = 0; cur < count; cur++) { h_parse_result_free(h_parse(parser, tc->input, tc->length)); } h_benchmark_clock_gettime(&ts_end); // time_diff is in ns time_diff = (ts_end.tv_sec - ts_start.tv_sec) * 1000000000 + (ts_end.tv_nsec - ts_start.tv_nsec); } while (time_diff < 100000000); ret->results[backend].cases[cur_case].parse_time = (time_diff / count); ret->results[backend].cases[cur_case].length = tc->length; cur_case++; } } return ret; }
HParser* h_difference__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { HTwoParsers *env = h_new(HTwoParsers, 1); env->p1 = p1; env->p2 = p2; return h_new_parser(mm__, &difference_vt, env); }
const HParser* h_ignore__m(HAllocator* mm__, const HParser* p) { HParser* ret = h_new(HParser, 1); ret->vtable = &ignore_vt; ret->env = (void*)p; return ret; }
// --------------------------------------------------------------------------- // Constructeur // ------------ bv310GridAIASCIIBaseAccessor ::bv310GridAIASCIIBaseAccessor( const char* hpath, int* status, int kind, int srid, double reso, double u2m, const char* name, const char* data) :bv310BaseAccessor(hpath,status,kind,srid,reso,u2m,name,data,2){ _bTrace_("bv310GridAIASCIIBaseAccessor::bv310GridAIASCIIBaseAccessor",true); char fname[FILENAME_MAX]; _nc=_nl=_ox=_oy=_csz=_ndv=0; _arr=NULL; _dvs.sign=_2D_VX; _dvs.nv=1; _dvs.no=0; _dvs.offs=NULL; _dvs.vx.vx2[0].x=_dvs.vx.vx2[0].y=0; for(;;){ load_data(hpath); sprintf(fname,"header"); *status=noErr; _hdr=(bStdTable*)wtbl_alloc(kTableLocalDBNoFU,"",fname,true,_reso,-1,status); if(*status<0){ _te_("_hdr=(bStdTable*)wtbl_alloc failed with "+(*status)); break; } /* sprintf(fname,"links"); *status=_fd; _lnks=(bStdTable*)wtbl_alloc(kTableLocalDBNoFU,"",fname,true,_reso,-1,status); if(*status<0){ _te_("_hdr=(bStdTable*)wtbl_alloc failed with "+(*status)); break; } // wtbl_free(_lnks); // _lnks=NULL; sprintf(fname,"constraints"); *status=_fd; _cnst=(bStdTable*)wtbl_alloc(kTableLocalDBNoFU,"",fname,true,_reso,-1,status); if(*status<0){ _te_("_cnst=(bStdTable*)wtbl_alloc failed with "+(*status)); break; } sprintf(fname,"fields"); *status=_fd; _fld=(bStdTable*)wtbl_alloc(kTableLocalDBNoFU,"",fname,true,_reso,-1,status); if(*status<0){ _te_("_fld=(bStdTable*)wtbl_alloc failed with "+(*status)); break; } sprintf(fname,"objects"); *status=noErr; _objs=(bStdTable*)wtbl_alloc(kTableLocalDBFU,"",fname,true,_reso,_srid,status); if(*status<0){ _te_("_objs=(bStdTable*)wtbl_alloc failed with "+(*status)); break; }*/ if((*status=h_new(name))){ _te_("h_new failed with "+(*status)); break; } /* if((*status=std_add())){ _te_("std_add failed with "+(*status)); break; } if(_fld->CountRecords()<kOBJ_Dir_){ _te_("_(_fld->CountRecords()<kOBJ_Dir_)"); *status=-1; break; }*/ if((*status=load(srid))){ _te_("load failed with "+(*status)); break; } return; } _te_("status == "+(*status)); _elts.reset(); _celts.reset(); if(_fld){ wtbl_free(_fld); _fld=NULL; } if(_objs){ wtbl_free(_objs); _objs=NULL; } if(_hdr){ wtbl_free(_hdr); _hdr=NULL; } if(_cnst){ wtbl_free(_cnst); _cnst=NULL; } if(_lnks){ wtbl_free(_lnks); _lnks=NULL; } if(_arr){ delete _arr; _arr=NULL; } }
HParser* h_get_value__m(HAllocator* mm__, const char* name) { HStoredValue *env = h_new(HStoredValue, 1); env->p = NULL; env->key = name; return h_new_parser(mm__, &get_vt, env); }
static HCFChoice* desugar_many(HAllocator *mm__, void *env) { HRepeat *repeat = (HRepeat*)env; /* many(A) => Ma -> A Mar -> \epsilon (but not if many1/sepBy1 is used) Mar -> Sep A Mar -> \epsilon */ HCFChoice *ret = h_new(HCFChoice, 1); ret->type = HCF_CHOICE; if (repeat->min_p) ret->seq = h_new(HCFSequence*, 2); /* choice of 1 sequence, A Mar */ else ret->seq = h_new(HCFSequence*, 3); /* choice of 2 sequences, A Mar | epsilon */ ret->seq[0] = h_new(HCFSequence, 1); ret->seq[0]->items = h_new(HCFChoice*, 2); /* create first subrule */ HCFChoice *ma = h_new(HCFChoice, 3); ma->type = HCF_CHOICE; ma->seq[0]->items[0] = h_desugar(mm__, repeat->p); /* create second subrule */ HCFChoice *mar = h_new(HCFChoice, 3); mar->type = HCF_CHOICE; mar->seq = h_new(HCFSequence*, 2); mar->seq[0] = h_new(HCFSequence, 1); mar->seq[0]->items = h_new(HCFChoice*, 4); mar->seq[0]->items[0] = h_desugar(mm__, repeat->sep); mar->seq[0]->items[1] = h_desugar(mm__, repeat->p);