Skip to content
Snippets Groups Projects
Commit d081cf42 authored by Sven M. Hallberg's avatar Sven M. Hallberg
Browse files

reshape bits parsers

parent c794be5b
No related branches found
No related tags found
No related merge requests found
......@@ -19,8 +19,8 @@ typedef struct HCFGrammar_ {
* therefore we must avoid 0 as a token value because NULL means "not in set".
*/
typedef uintptr_t HCFToken;
static inline HCFToken char_token(char c) { return (0x100 | c); }
static inline char token_char(HCFToken t) { return (0xFF & t); }
static inline HCFToken char_token(uint8_t c) { return (0x100 | c); }
static inline uint8_t token_char(HCFToken t) { return (0xFF & t); }
static const HCFToken end_token = 0x200;
......
......@@ -17,6 +17,41 @@ static HParseResult* parse_bits(void* env, HParseState *state) {
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) {
struct bits_env *bits = (struct bits_env*)env;
if (0 != bits->length % 8)
......@@ -46,6 +81,11 @@ static HCFChoice* desugar_bits(HAllocator *mm__, void *env) {
ret->seq[1] = NULL;
ret->action = NULL;
if(bits->signedp)
ret->reshape = reshape_bits_signed;
else
ret->reshape = reshape_bits_unsigned;
return ret;
}
......
......@@ -41,6 +41,13 @@ static void test_int32(void) {
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) {
const HParser *int16_ = h_int16();
......@@ -48,6 +55,13 @@ static void test_int16(void) {
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) {
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/int64", test_int64);
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_pos", test_int16_pos);
g_test_add_func("/core/parser/int8", test_int8);
g_test_add_func("/core/parser/uint64", test_uint64);
g_test_add_func("/core/parser/uint32", test_uint32);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment