reshape bits parsers
This commit is contained in:
parent
c794be5b6f
commit
d081cf4284
3 changed files with 58 additions and 2 deletions
|
|
@ -19,8 +19,8 @@ typedef struct HCFGrammar_ {
|
||||||
* therefore we must avoid 0 as a token value because NULL means "not in set".
|
* therefore we must avoid 0 as a token value because NULL means "not in set".
|
||||||
*/
|
*/
|
||||||
typedef uintptr_t HCFToken;
|
typedef uintptr_t HCFToken;
|
||||||
static inline HCFToken char_token(char c) { return (0x100 | c); }
|
static inline HCFToken char_token(uint8_t c) { return (0x100 | c); }
|
||||||
static inline char token_char(HCFToken t) { return (0xFF & t); }
|
static inline uint8_t token_char(HCFToken t) { return (0xFF & t); }
|
||||||
static const HCFToken end_token = 0x200;
|
static const HCFToken end_token = 0x200;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,41 @@ static HParseResult* parse_bits(void* env, HParseState *state) {
|
||||||
return make_result(state->arena, result);
|
return make_result(state->arena, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HParsedToken *reshape_bits(const HParseResult *p, bool signedp) {
|
||||||
|
// XXX works only for whole bytes
|
||||||
|
// XXX assumes big-endian
|
||||||
|
assert(p->ast);
|
||||||
|
assert(p->ast->token_type == TT_SEQUENCE);
|
||||||
|
|
||||||
|
HCountedArray *seq = p->ast->seq;
|
||||||
|
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
|
||||||
|
ret->token_type = TT_UINT;
|
||||||
|
|
||||||
|
if(signedp && (seq->elements[0]->uint & 128))
|
||||||
|
ret->uint = -1; // all ones
|
||||||
|
|
||||||
|
for(size_t i=0; i<seq->used; i++) {
|
||||||
|
HParsedToken *t = seq->elements[i];
|
||||||
|
assert(t->token_type == TT_UINT);
|
||||||
|
|
||||||
|
ret->uint <<= 8;
|
||||||
|
ret->uint |= t->uint & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(signedp) {
|
||||||
|
ret->token_type = TT_SINT;
|
||||||
|
ret->sint = ret->uint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static const HParsedToken *reshape_bits_unsigned(const HParseResult *p) {
|
||||||
|
return reshape_bits(p, false);
|
||||||
|
}
|
||||||
|
static const HParsedToken *reshape_bits_signed(const HParseResult *p) {
|
||||||
|
return reshape_bits(p, true);
|
||||||
|
}
|
||||||
|
|
||||||
static HCFChoice* desugar_bits(HAllocator *mm__, void *env) {
|
static HCFChoice* desugar_bits(HAllocator *mm__, void *env) {
|
||||||
struct bits_env *bits = (struct bits_env*)env;
|
struct bits_env *bits = (struct bits_env*)env;
|
||||||
if (0 != bits->length % 8)
|
if (0 != bits->length % 8)
|
||||||
|
|
@ -46,6 +81,11 @@ static HCFChoice* desugar_bits(HAllocator *mm__, void *env) {
|
||||||
ret->seq[1] = NULL;
|
ret->seq[1] = NULL;
|
||||||
ret->action = NULL;
|
ret->action = NULL;
|
||||||
|
|
||||||
|
if(bits->signedp)
|
||||||
|
ret->reshape = reshape_bits_signed;
|
||||||
|
else
|
||||||
|
ret->reshape = reshape_bits_unsigned;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,13 @@ static void test_int32(void) {
|
||||||
g_check_parse_failed(int32_, "\xff\xfe\x00", 3);
|
g_check_parse_failed(int32_, "\xff\xfe\x00", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_int32_pos(void) {
|
||||||
|
const HParser *int32_ = h_int32();
|
||||||
|
|
||||||
|
g_check_parse_ok(int32_, "\x00\x02\x00\x00", 4, "s0x20000");
|
||||||
|
g_check_parse_failed(int32_, "\x00\x02\x00", 3);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_int16(void) {
|
static void test_int16(void) {
|
||||||
const HParser *int16_ = h_int16();
|
const HParser *int16_ = h_int16();
|
||||||
|
|
||||||
|
|
@ -48,6 +55,13 @@ static void test_int16(void) {
|
||||||
g_check_parse_failed(int16_, "\xfe", 1);
|
g_check_parse_failed(int16_, "\xfe", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_int16_pos(void) {
|
||||||
|
const HParser *int16_ = h_int16();
|
||||||
|
|
||||||
|
g_check_parse_ok(int16_, "\x02\x00", 2, "s0x200");
|
||||||
|
g_check_parse_failed(int16_, "\x02", 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_int8(void) {
|
static void test_int8(void) {
|
||||||
const HParser *int8_ = h_int8();
|
const HParser *int8_ = h_int8();
|
||||||
|
|
||||||
|
|
@ -395,7 +409,9 @@ void register_parser_tests(void) {
|
||||||
g_test_add_func("/core/parser/ch_range", test_ch_range);
|
g_test_add_func("/core/parser/ch_range", test_ch_range);
|
||||||
g_test_add_func("/core/parser/int64", test_int64);
|
g_test_add_func("/core/parser/int64", test_int64);
|
||||||
g_test_add_func("/core/parser/int32", test_int32);
|
g_test_add_func("/core/parser/int32", test_int32);
|
||||||
|
g_test_add_func("/core/parser/int32_pos", test_int32_pos);
|
||||||
g_test_add_func("/core/parser/int16", test_int16);
|
g_test_add_func("/core/parser/int16", test_int16);
|
||||||
|
g_test_add_func("/core/parser/int16_pos", test_int16_pos);
|
||||||
g_test_add_func("/core/parser/int8", test_int8);
|
g_test_add_func("/core/parser/int8", test_int8);
|
||||||
g_test_add_func("/core/parser/uint64", test_uint64);
|
g_test_add_func("/core/parser/uint64", test_uint64);
|
||||||
g_test_add_func("/core/parser/uint32", test_uint32);
|
g_test_add_func("/core/parser/uint32", test_uint32);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue