diff --git a/examples/base64_sem1.c b/examples/base64_sem1.c index 6dbb2fd348eef48c9bf1a86bda54288cde9602e9..5e1673a28a2603043944992a8d399cdbb98df01c 100644 --- a/examples/base64_sem1.c +++ b/examples/base64_sem1.c @@ -125,14 +125,37 @@ const HParsedToken *act_base64_1(const HParseResult *p) return act_base64_n(1, p); } -#if 0 +// Helper to concatenate two arrays. +void carray_concat(HCountedArray *a, const HCountedArray *b) +{ + for(size_t i=0; i<b->used; i++) + h_carray_append(a, b->elements[i]); +} + const HParsedToken *act_base64(const HParseResult *p) { - // XXX + assert(p->ast->token_type == TT_SEQUENCE); + assert(p->ast->seq->used == 2); + assert(p->ast->seq->elements[0]->token_type == TT_SEQUENCE); + + HParsedToken *res = h_arena_malloc(p->arena, sizeof(HParsedToken)); + res->token_type = TT_SEQUENCE; + res->seq = h_carray_new(p->arena); + // concatenate base64_3 blocks - // append trailing base64_2 or _1 block + HCountedArray *seq = p->ast->seq->elements[0]->seq; + for(size_t i=0; i<seq->used; i++) { + assert(seq->elements[i]->token_type == TT_SEQUENCE); + carray_concat(res->seq, seq->elements[i]->seq); + } + + // append one trailing base64_2 or _1 block + const HParsedToken *tok = p->ast->seq->elements[1]; + if(tok->token_type == TT_SEQUENCE) + carray_concat(res->seq, tok->seq); + + return res; } -#endif /// @@ -157,7 +180,7 @@ const HParser *init_parser(void) H_ARULE(base64_3, h_repeat_n(bsfdig, 4)); H_ARULE(base64_2, h_sequence(bsfdig, bsfdig, bsfdig_4bit, equals, NULL)); H_ARULE(base64_1, h_sequence(bsfdig, bsfdig_2bit, equals, equals, NULL)); - H_RULE(base64, h_sequence(h_many(base64_3), + H_ARULE(base64, h_sequence(h_many(base64_3), h_optional(h_choice(base64_2, base64_1, NULL)), NULL));