From 9494c08f360b9980cc08f254feb742b08fbc081d Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sat, 26 Oct 2024 15:38:48 +0100 Subject: [PATCH] Write invariant tests for desugaring --- lib/desugar.c | 12 ++++ lib/desugar.h | 13 ++++ scripts/build.sh | 5 +- scripts/test.sh | 1 + tests/desugar_tests.c | 159 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/desugar.c create mode 100644 lib/desugar.h create mode 100644 tests/desugar_tests.c diff --git a/lib/desugar.c b/lib/desugar.c new file mode 100644 index 0000000..b45749e --- /dev/null +++ b/lib/desugar.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) Camden Dixie O'Brien + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#include "desugar.h" + +#include + +void desugar_regex(parse_tree_t *regex) +{ +} diff --git a/lib/desugar.h b/lib/desugar.h new file mode 100644 index 0000000..a688667 --- /dev/null +++ b/lib/desugar.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) Camden Dixie O'Brien + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#ifndef DESUGAR_H +#define DESUGAR_H + +#include "parse.h" + +void desugar_regex(parse_tree_t *regex); + +#endif diff --git a/scripts/build.sh b/scripts/build.sh index 8a41d1c..f7b2401 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -8,9 +8,12 @@ if [ ! -e build ]; then mkdir build; else rm build/*; fi # Build library clang $CFLAGS -Ilib -c lib/parse.c -o build/parse.o -ar -crs build/lib.a build/parse.o build/regex.o +clang $CFLAGS -Ilib -c lib/desugar.c -o build/desugar.o +ar -crs build/lib.a build/parse.o build/desugar.o # Build tests clang $CFLAGS -Itests -c tests/testing.c -o build/testing.o clang $CFLAGS -Ilib -Itests -o build/parse_tests \ tests/parse_tests.c build/testing.o build/lib.a +clang $CFLAGS -Ilib -Itests -o build/desugar_tests \ + tests/desugar_tests.c build/testing.o build/lib.a diff --git a/scripts/test.sh b/scripts/test.sh index 981ecfc..2e918c9 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -3,5 +3,6 @@ cd "$(git rev-parse --show-toplevel)" fails=0 build/parse_tests || fails=`expr $fails + 1` +build/desugar_tests || fails=`expr $fails + 1` if [ $fails -eq 0 ]; then echo Tests OK; fi diff --git a/tests/desugar_tests.c b/tests/desugar_tests.c new file mode 100644 index 0000000..b5866de --- /dev/null +++ b/tests/desugar_tests.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) Camden Dixie O'Brien + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#include "desugar.h" +#include "testing.h" + +#include + +static void a_is_unchanged(void) +{ + parse_term_t *terms = malloc(1 * sizeof(parse_term_t)); + terms[0].quantifier = PARSE_QUANTIFIER_NONE; + terms[0].type = PARSE_TERM_LITERAL; + terms[0].literal = 'a'; + parse_sequence_t *alternatives = malloc(1 * sizeof(parse_sequence_t)); + alternatives[0].len = alternatives[0].capacity = 1; + alternatives[0].contents = terms; + parse_tree_t t + = { .count = 1, .capacity = 1, .alternatives = alternatives }; + + desugar_regex(&t); + ASSERT_EQ(1, t.count); + ASSERT_NOT_NULL(t.alternatives); + ASSERT_EQ(1, t.alternatives[0].len); + ASSERT_NOT_NULL(t.alternatives[0].contents); + ASSERT_EQ( + PARSE_QUANTIFIER_NONE, t.alternatives[0].contents[0].quantifier); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[0].contents[0].type); + ASSERT_EQ('a', t.alternatives[0].contents[0].literal); + + parse_free_tree_children(&t); +} + +static void abc_is_unchanged(void) +{ + parse_term_t *terms = malloc(3 * sizeof(parse_term_t)); + terms[0].type = PARSE_TERM_LITERAL; + terms[0].literal = 'a'; + terms[1].type = PARSE_TERM_LITERAL; + terms[1].literal = 'b'; + terms[2].type = PARSE_TERM_LITERAL; + terms[2].literal = 'c'; + parse_sequence_t *alternatives = malloc(1 * sizeof(parse_sequence_t)); + alternatives[0].len = alternatives[0].capacity = 3; + alternatives[0].contents = terms; + parse_tree_t t + = { .count = 1, .capacity = 1, .alternatives = alternatives }; + + desugar_regex(&t); + ASSERT_EQ(1, t.count); + ASSERT_NOT_NULL(t.alternatives); + ASSERT_EQ(3, t.alternatives[0].len); + ASSERT_NOT_NULL(t.alternatives[0].contents); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[0].contents[0].type); + ASSERT_EQ('a', t.alternatives[0].contents[0].literal); + ASSERT_NOT_NULL(t.alternatives[0].contents); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[0].contents[1].type); + ASSERT_EQ('b', t.alternatives[0].contents[1].literal); + ASSERT_NOT_NULL(t.alternatives[0].contents); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[0].contents[2].type); + ASSERT_EQ('c', t.alternatives[0].contents[2].literal); + + parse_free_tree_children(&t); +} + +static void a_star_is_unchanged(void) +{ + parse_term_t *terms = malloc(1 * sizeof(parse_term_t)); + terms[0].quantifier = PARSE_QUANTIFIER_STAR; + terms[0].type = PARSE_TERM_LITERAL; + terms[0].literal = 'a'; + parse_sequence_t *alternatives = malloc(1 * sizeof(parse_sequence_t)); + alternatives[0].len = alternatives[0].capacity = 1; + alternatives[0].contents = terms; + parse_tree_t t + = { .count = 1, .capacity = 1, .alternatives = alternatives }; + + desugar_regex(&t); + ASSERT_EQ(1, t.count); + ASSERT_NOT_NULL(t.alternatives); + ASSERT_EQ(1, t.alternatives[0].len); + ASSERT_NOT_NULL(t.alternatives[0].contents); + ASSERT_EQ( + PARSE_QUANTIFIER_STAR, t.alternatives[0].contents[0].quantifier); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[0].contents[0].type); + ASSERT_EQ('a', t.alternatives[0].contents[0].literal); + + parse_free_tree_children(&t); +} + +static void a_or_b_or_c_is_unchanged(void) +{ + const char *literals = "abc"; + parse_sequence_t *alternatives = malloc(3 * sizeof(parse_sequence_t)); + for (int i = 0; i < 3; ++i) { + parse_term_t *terms = malloc(1 * sizeof(parse_term_t)); + terms[0].quantifier = PARSE_QUANTIFIER_NONE; + terms[0].type = PARSE_TERM_LITERAL; + terms[0].literal = literals[i]; + + alternatives[i].len = alternatives[i].capacity = 1; + alternatives[i].contents = terms; + } + parse_tree_t t + = { .count = 3, .capacity = 3, .alternatives = alternatives }; + + desugar_regex(&t); + ASSERT_EQ(3, t.count); + ASSERT_NOT_NULL(t.alternatives); + for (int i = 0; i < 3; ++i) { + ASSERT_EQ(1, t.alternatives[i].len); + ASSERT_NOT_NULL(t.alternatives[i].contents); + ASSERT_EQ( + PARSE_QUANTIFIER_NONE, t.alternatives[i].contents[0].quantifier); + ASSERT_EQ(PARSE_TERM_LITERAL, t.alternatives[i].contents[0].type); + ASSERT_EQ(literals[i], t.alternatives[i].contents[0].literal); + } + + parse_free_tree_children(&t); +} + +static void subexpr_a_is_unchanged(void) +{ + parse_term_t *inner_terms = malloc(1 * sizeof(parse_term_t)); + inner_terms[0].quantifier = PARSE_QUANTIFIER_NONE; + inner_terms[0].type = PARSE_TERM_LITERAL; + inner_terms[0].literal = 'a'; + parse_sequence_t *inner_alternatives + = malloc(1 * sizeof(parse_sequence_t)); + inner_alternatives[0].len = inner_alternatives[0].capacity = 1; + inner_alternatives[0].contents = inner_terms; + parse_term_t *terms = malloc(1 * sizeof(parse_term_t)); + terms[0].quantifier = PARSE_QUANTIFIER_NONE; + terms[0].type = PARSE_TERM_SUBEXPR; + terms[0].subexpr.count = terms[0].subexpr.capacity = 1; + terms[0].subexpr.alternatives = inner_alternatives; + parse_sequence_t *alternatives = malloc(1 * sizeof(parse_sequence_t)); + alternatives[0].len = alternatives[0].capacity = 1; + alternatives[0].contents = terms; + parse_tree_t t + = { .count = 1, .capacity = 1, .alternatives = alternatives }; + + desugar_regex(&t); + + parse_free_tree_children(&t); +} + +int main(void) +{ + TESTING_BEGIN(); + a_is_unchanged(); + abc_is_unchanged(); + a_star_is_unchanged(); + a_or_b_or_c_is_unchanged(); + subexpr_a_is_unchanged(); + return TESTING_END(); +}