diff --git a/lib/desugar.c b/lib/desugar.c index b45749e..bbc7afd 100644 --- a/lib/desugar.c +++ b/lib/desugar.c @@ -5,8 +5,70 @@ #include "desugar.h" +#include #include +#include + +static void deep_copy_term(parse_term_t *dst, parse_term_t *src); + +static void deep_copy_sequence(parse_sequence_t *dst, parse_sequence_t *src) +{ + dst->count = dst->capacity = src->count; + dst->contents = malloc(dst->capacity * sizeof(parse_term_t)); + for (int i = 0; i < dst->count; ++i) + deep_copy_term(&dst->contents[i], &src->contents[i]); +} + +static void deep_copy_term(parse_term_t *dst, parse_term_t *src) +{ + assert(PARSE_TERM_WILDCARD != src->type); + assert(PARSE_TERM_CLASS != src->type); + + memcpy(dst, src, sizeof(parse_term_t)); + if (PARSE_TERM_SUBEXPR == src->type) { + dst->subexpr.capacity = src->subexpr.count; + dst->subexpr.contents + = malloc(dst->subexpr.capacity * sizeof(parse_sequence_t)); + for (int i = 0; i < dst->subexpr.count; ++i) { + deep_copy_sequence( + &dst->subexpr.contents[i], &src->subexpr.contents[i]); + } + } +} + +static void desugar_plus(parse_term_t *term) +{ + parse_sequence_t *alternatives = malloc(sizeof(parse_sequence_t)); + alternatives[0].count = alternatives[0].capacity = 2; + alternatives[0].contents = malloc(2 * sizeof(parse_term_t)); + + memcpy(&alternatives[0].contents[0], term, sizeof(parse_term_t)); + deep_copy_term(&alternatives[0].contents[1], term); + alternatives[0].contents[0].quantifier = PARSE_QUANTIFIER_NONE; + alternatives[0].contents[1].quantifier = PARSE_QUANTIFIER_STAR; + + term->quantifier = PARSE_QUANTIFIER_NONE; + term->type = PARSE_TERM_SUBEXPR; + term->subexpr.count = term->subexpr.capacity = 1; + term->subexpr.contents = alternatives; +} + +static void desugar_term(parse_term_t *term) +{ + switch (term->quantifier) { + case PARSE_QUANTIFIER_PLUS: + desugar_plus(term); + break; + case PARSE_QUANTIFIER_NONE: + case PARSE_QUANTIFIER_STAR: + break; + } +} void desugar_regex(parse_tree_t *regex) { + for (int i = 0; i < regex->count; ++i) { + for (int j = 0; j < regex->contents[i].count; ++j) + desugar_term(®ex->contents[i].contents[j]); + } } diff --git a/tests/desugar_tests.c b/tests/desugar_tests.c index 6119fa9..d3902bf 100644 --- a/tests/desugar_tests.c +++ b/tests/desugar_tests.c @@ -140,6 +140,42 @@ static void subexpr_a_is_unchanged(void) parse_free_tree_children(&t); } +static void a_plus_becomes_subexpr_aa_star(void) +{ + parse_term_t *terms = malloc(1 * sizeof(parse_term_t)); + terms[0].quantifier = PARSE_QUANTIFIER_PLUS; + terms[0].type = PARSE_TERM_LITERAL; + terms[0].literal = 'a'; + parse_sequence_t *alternatives = malloc(1 * sizeof(parse_sequence_t)); + alternatives[0].count = alternatives[0].capacity = 1; + alternatives[0].contents = terms; + parse_tree_t t = { .count = 1, .capacity = 1, .contents = alternatives }; + + desugar_regex(&t); + ASSERT_EQ(1, t.count); + ASSERT_NOT_NULL(t.contents); + ASSERT_EQ(1, t.contents[0].count); + ASSERT_NOT_NULL(t.contents[0].contents); + ASSERT_EQ(PARSE_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); + ASSERT_EQ(PARSE_TERM_SUBEXPR, t.contents[0].contents[0].type); + + const parse_tree_t *inner = &t.contents[0].contents[0].subexpr; + ASSERT_EQ(1, inner->count); + ASSERT_NOT_NULL(inner->contents); + ASSERT_EQ(2, inner->contents[0].count); + ASSERT_NOT_NULL(inner->contents[0].contents); + ASSERT_EQ( + PARSE_QUANTIFIER_NONE, inner->contents[0].contents[0].quantifier); + ASSERT_EQ(PARSE_TERM_LITERAL, inner->contents[0].contents[0].type); + ASSERT_EQ('a', inner->contents[0].contents[0].literal); + ASSERT_EQ( + PARSE_QUANTIFIER_STAR, inner->contents[0].contents[1].quantifier); + ASSERT_EQ(PARSE_TERM_LITERAL, inner->contents[0].contents[1].type); + ASSERT_EQ('a', inner->contents[0].contents[1].literal); + + parse_free_tree_children(&t); +} + int main(void) { TESTING_BEGIN(); @@ -148,5 +184,6 @@ int main(void) a_star_is_unchanged(); a_or_b_or_c_is_unchanged(); subexpr_a_is_unchanged(); + a_plus_becomes_subexpr_aa_star(); return TESTING_END(); }