diff --git a/examples/dns_common.c b/examples/dns_common.c index f05a3e6..9f02fc6 100644 --- a/examples/dns_common.c +++ b/examples/dns_common.c @@ -44,14 +44,16 @@ const HParsedToken* act_domain(const HParseResult *p) { } if(arr) { - dns_domain_t *val = H_MAKE(dns_domain); // dns_domain_t is char* + dns_domain_t *val = H_MAKE(dns_domain_t); // dns_domain_t is char* *val = arr; - ret = H_MAKE_TOKEN(dns_domain, val); + ret = H_MAKE_TOKEN(dns_domain_t, val); } return ret; } +#define act_label_ act_flatten + const HParser* init_domain() { static const HParser *ret = NULL; if (ret) @@ -60,12 +62,12 @@ const HParser* init_domain() { H_RULE (letter, h_choice(h_ch_range('a','z'), h_ch_range('A','Z'), NULL)); H_RULE (let_dig, h_choice(letter, h_ch_range('0','9'), NULL)); H_RULE (ldh_str, h_many1(h_choice(let_dig, h_ch('-'), NULL))); - H_RULE (label, h_attr_bool(h_sequence(letter, - h_optional(h_sequence(h_optional(ldh_str), - let_dig, - NULL)), - NULL), - validate_label)); + H_ARULE(label_, h_sequence(letter, + h_optional(h_sequence(h_optional(ldh_str), + let_dig, + NULL)), + NULL)); + H_RULE (label, h_attr_bool(label_, validate_label)); H_RULE (subdomain, h_sepBy1(label, h_ch('.'))); H_ARULE(domain, h_choice(subdomain, h_ch(' '), NULL)); diff --git a/examples/glue.c b/examples/glue.c index 767f853..b635d7c 100644 --- a/examples/glue.c +++ b/examples/glue.c @@ -1,4 +1,5 @@ #include "glue.h" +#include "../src/internal.h" // for h_carray_* // The action equivalent of h_ignore. @@ -31,10 +32,68 @@ const HParsedToken *act_index0(const HParseResult *p) return act_index(0, p); } -HParsedToken *h_make_token(HArena *arena, HTokenType type, void *value) +void h_seq_snoc(HParsedToken *xs, const HParsedToken *x) +{ + assert(xs != NULL); + assert(xs->token_type == TT_SEQUENCE); + + h_carray_append(xs->seq, (void *)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; iseq->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_token_flatten(HArena *arena, const HParsedToken *p) +{ + assert(p != NULL); + + HParsedToken *ret = h_make_token_seq(arena); + switch(p->token_type) { + case TT_SEQUENCE: + // Flatten and append all. + for(size_t i; iseq->used; i++) { + h_seq_append(ret, h_token_flatten(arena, h_seq_index(p, i))); + } + break; + default: + // Make singleton sequence. + h_seq_snoc(ret, p); + break; + } + + return ret; +} + +// Action version of h_token_flatten. +const HParsedToken *act_flatten(const HParseResult *p) { + return h_token_flatten(p->arena, p->ast); +} + +HParsedToken *h_make_token_(HArena *arena, HTokenType type) { HParsedToken *ret = h_arena_malloc(arena, sizeof(HParsedToken)); ret->token_type = type; + return ret; +} + +HParsedToken *h_make_token_seq(HArena *arena) +{ + return h_make_token_(arena, TT_SEQUENCE); +} + +HParsedToken *h_make_token(HArena *arena, HTokenType type, void *value) +{ + HParsedToken *ret = h_make_token_(arena, type); ret->user = value; return ret; } diff --git a/examples/glue.h b/examples/glue.h index 88b788d..c65f7b4 100644 --- a/examples/glue.h +++ b/examples/glue.h @@ -14,8 +14,15 @@ const HParsedToken *act_ignore(const HParseResult *p); const HParsedToken *act_index(int i, const HParseResult *p); const HParsedToken *act_index0(const HParseResult *p); +const HParsedToken *act_flatten(const HParseResult *p); + +const HParsedToken *h_token_flatten(HArena *arena, const HParsedToken *p); + +void h_seq_snoc(HParsedToken *xs, const HParsedToken *x); +void h_seq_append(HParsedToken *xs, const HParsedToken *ys); HParsedToken *h_make_token(HArena *arena, HTokenType type, void *value); +HParsedToken *h_make_token_seq(HArena *arena); #define H_MAKE(TYP) \ ((TYP *) h_arena_malloc(p->arena, sizeof(TYP)))