#include <assert.h> #include "glue.h" #include "hammer.h" #include "internal.h" // for h_carray_* #include "parsers/parser_internal.h" // Helper to build HAction's that pick one index out of a sequence. HParsedToken *h_act_index(int i, const HParseResult *p, void* user_data) { if(!p) return NULL; const HParsedToken *tok = p->ast; if(!tok || tok->token_type != TT_SEQUENCE) return NULL; const HCountedArray *seq = tok->seq; size_t n = seq->used; if(i<0 || (size_t)i>=n) return NULL; else return tok->seq->elements[i]; } HParsedToken *h_act_first(const HParseResult *p, void* user_data) { assert(p->ast); assert(p->ast->token_type == TT_SEQUENCE); assert(p->ast->seq->used > 0); return p->ast->seq->elements[0]; } HParsedToken *h_act_second(const HParseResult *p, void* user_data) { assert(p->ast); assert(p->ast->token_type == TT_SEQUENCE); assert(p->ast->seq->used > 0); return p->ast->seq->elements[1]; } HParsedToken *h_act_last(const HParseResult *p, void* user_data) { assert(p->ast); assert(p->ast->token_type == TT_SEQUENCE); assert(p->ast->seq->used > 0); return p->ast->seq->elements[p->ast->seq->used-1]; } static void act_flatten_(HCountedArray *seq, const HParsedToken *tok) { if(tok == NULL) { return; } else if(tok->token_type == TT_SEQUENCE) { size_t i; for(i=0; i<tok->seq->used; i++) act_flatten_(seq, tok->seq->elements[i]); } else { h_carray_append(seq, (HParsedToken *)tok); } } HParsedToken *h_act_flatten(const HParseResult *p, void* user_data) { HCountedArray *seq = h_carray_new(p->arena); act_flatten_(seq, p->ast); HParsedToken *res = a_new_(p->arena, HParsedToken, 1); res->token_type = TT_SEQUENCE; res->seq = seq; res->index = p->ast->index; res->bit_offset = p->ast->bit_offset; return res; } HParsedToken *h_act_ignore(const HParseResult *p, void* user_data) { return NULL; } // Low-level helper for the h_make family. HParsedToken *h_make_(HArena *arena, HTokenType type) { HParsedToken *ret = h_arena_malloc(arena, sizeof(HParsedToken)); ret->token_type = type; return ret; } HParsedToken *h_make(HArena *arena, HTokenType type, void *value) { assert(type >= TT_USER); HParsedToken *ret = h_make_(arena, type); ret->user = value; return ret; } HParsedToken *h_make_seq(HArena *arena) { HParsedToken *ret = h_make_(arena, TT_SEQUENCE); ret->seq = h_carray_new(arena); return ret; } HParsedToken *h_make_seqn(HArena *arena, size_t n) { HParsedToken *ret = h_make_(arena, TT_SEQUENCE); ret->seq = h_carray_new_sized(arena, n); return ret; } HParsedToken *h_make_bytes(HArena *arena, uint8_t *array, size_t len) { HParsedToken *ret = h_make_(arena, TT_BYTES); ret->bytes.len = len; ret->bytes.token = array; return ret; } HParsedToken *h_make_sint(HArena *arena, int64_t val) { HParsedToken *ret = h_make_(arena, TT_SINT); ret->sint = val; return ret; } HParsedToken *h_make_uint(HArena *arena, uint64_t val) { HParsedToken *ret = h_make_(arena, TT_UINT); ret->uint = val; return ret; } // XXX -> internal HParsedToken *h_carray_index(const HCountedArray *a, size_t i) { assert(i < a->used); return a->elements[i]; } size_t h_seq_len(const HParsedToken *p) { assert(p != NULL); assert(p->token_type == TT_SEQUENCE); return p->seq->used; } HParsedToken **h_seq_elements(const HParsedToken *p) { assert(p != NULL); assert(p->token_type == TT_SEQUENCE); return p->seq->elements; } HParsedToken *h_seq_index(const HParsedToken *p, size_t i) { assert(p != NULL); assert(p->token_type == TT_SEQUENCE); return h_carray_index(p->seq, i); } HParsedToken *h_seq_index_path(const HParsedToken *p, size_t i, ...) { va_list va; va_start(va, i); HParsedToken *ret = h_seq_index_vpath(p, i, va); va_end(va); return ret; } HParsedToken *h_seq_index_vpath(const HParsedToken *p, size_t i, va_list va) { HParsedToken *ret = h_seq_index(p, i); int j; while((j = va_arg(va, int)) >= 0) ret = h_seq_index(ret, j); return ret; } void h_seq_snoc(HParsedToken *xs, const HParsedToken *x) { assert(xs != NULL); assert(xs->token_type == TT_SEQUENCE); h_carray_append(xs->seq, (HParsedToken *)x); } void h_seq_append(HParsedToken *xs, const HParsedToken *ys) { assert(xs != NULL); assert(xs->token_type == TT_SEQUENCE); assert(ys != NULL); assert(ys->token_type == TT_SEQUENCE); for(size_t i=0; i<ys->seq->used; i++) h_carray_append(xs->seq, ys->seq->elements[i]); } // Flatten nested sequences. Always returns a sequence. // If input element is not a sequence, returns it as a singleton sequence. const HParsedToken *h_seq_flatten(HArena *arena, const HParsedToken *p) { assert(p != NULL); HParsedToken *ret = h_make_seq(arena); switch(p->token_type) { case TT_SEQUENCE: // Flatten and append all. for(size_t i = 0; i<p->seq->used; i++) { h_seq_append(ret, h_seq_flatten(arena, h_seq_index(p, i))); } break; default: // Make singleton sequence. h_seq_snoc(ret, p); break; } return ret; }