/* * Copyright (c) Camden Dixie O'Brien * SPDX-License-Identifier: AGPL-3.0-only */ #include "parse.h" #include "testing.h" #define PARSE_EXPR_STRING(s, r) parse_expr(s, strlen(s), r) static void a_has_1_alternative(void) { regex_t t; const int result = PARSE_EXPR_STRING("a", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); regex_free_children(&t); } static void a_pipe_b_has_2_alternatives(void) { regex_t t; const int result = PARSE_EXPR_STRING("a|b", &t); ASSERT_NE(-1, result); ASSERT_EQ(2, t.count); regex_free_children(&t); } static void a_pipe_b_pipe_c_has_3_alternatives(void) { regex_t t; const int result = PARSE_EXPR_STRING("a|b|c", &t); ASSERT_NE(-1, result); ASSERT_EQ(3, t.count); regex_free_children(&t); } static void a_is_parsed_as_unquantified_literal(void) { regex_t t; const int result = PARSE_EXPR_STRING("a", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[0].type); ASSERT_EQ('a', t.contents[0].contents[0].literal); regex_free_children(&t); } static void b_is_parsed_as_unquantified_literal(void) { regex_t t; const int result = PARSE_EXPR_STRING("b", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[0].type); ASSERT_EQ('b', t.contents[0].contents[0].literal); regex_free_children(&t); } static void abc_is_parsed_as_sequence_of_unquantified_literals(void) { regex_t t; const int result = PARSE_EXPR_STRING("abc", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(3, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[0].type); ASSERT_EQ('a', t.contents[0].contents[0].literal); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[1].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[1].type); ASSERT_EQ('b', t.contents[0].contents[1].literal); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[2].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[2].type); ASSERT_EQ('c', t.contents[0].contents[2].literal); regex_free_children(&t); } static void dot_is_parsed_as_unquantified_wildcard_term(void) { regex_t t; const int result = PARSE_EXPR_STRING(".", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_WILDCARD, t.contents[0].contents[0].type); regex_free_children(&t); } static void backslash_dot_is_parsed_as_unquantified_literal(void) { regex_t t; const int result = PARSE_EXPR_STRING("\\.", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[0].type); ASSERT_EQ('.', t.contents[0].contents[0].literal); regex_free_children(&t); } static void backslash_backslash_is_parsed_as_unquantified_literal(void) { regex_t t; const int result = PARSE_EXPR_STRING("\\\\", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[0].type); ASSERT_EQ('\\', t.contents[0].contents[0].literal); regex_free_children(&t); } static void a_pipe_b_in_parens_is_parsed_as_subexpr_term(void) { regex_t t; const int result = PARSE_EXPR_STRING("(a|b)", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_SUBEXPR, t.contents[0].contents[0].type); const regex_t *inner = &t.contents[0].contents[0].subexpr; ASSERT_EQ(2, inner->count); ASSERT_EQ(1, inner->contents[0].count); ASSERT_EQ( REGEX_QUANTIFIER_NONE, inner->contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, inner->contents[0].contents[0].type); ASSERT_EQ('a', inner->contents[0].contents[0].literal); ASSERT_EQ(1, inner->contents[1].count); ASSERT_EQ( REGEX_QUANTIFIER_NONE, inner->contents[1].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, inner->contents[1].contents[0].type); ASSERT_EQ('b', inner->contents[1].contents[0].literal); regex_free_children(&t); } static void a_in_parens_b_is_parsed_as_sequence_with_subexpr_term(void) { regex_t t; const int result = PARSE_EXPR_STRING("(a)b", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(2, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_SUBEXPR, t.contents[0].contents[0].type); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[1].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, t.contents[0].contents[1].type); ASSERT_EQ('b', t.contents[0].contents[1].literal); const regex_t *inner = &t.contents[0].contents[0].subexpr; ASSERT_EQ(1, inner->contents[0].count); ASSERT_EQ( REGEX_QUANTIFIER_NONE, inner->contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_LITERAL, inner->contents[0].contents[0].type); ASSERT_EQ('a', inner->contents[0].contents[0].literal); regex_free_children(&t); } static void dot_star_is_parsed_as_star_quantified_wildcard(void) { regex_t t; const int result = PARSE_EXPR_STRING(".*", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_STAR, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_WILDCARD, t.contents[0].contents[0].type); regex_free_children(&t); } static void dot_plus_is_parsed_as_plus_quantified_wildcard(void) { regex_t t; const int result = PARSE_EXPR_STRING(".+", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_PLUS, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_WILDCARD, t.contents[0].contents[0].type); regex_free_children(&t); } static void dot_question_mark_is_parsed_as_qmrk_quantified_wildcard(void) { regex_t t; const int result = PARSE_EXPR_STRING(".?", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_QMARK, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_WILDCARD, t.contents[0].contents[0].type); regex_free_children(&t); } static void a_in_brackets_is_parsed_as_class_containing_only_a(void) { regex_t t; const int result = PARSE_EXPR_STRING("[a]", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_CLASS, t.contents[0].contents[0].type); ASSERT_FALSE(t.contents[0].contents[0].class.negated); ASSERT_EQ(1, t.contents[0].contents[0].class.count); ASSERT_NOT_NULL(t.contents[0].contents[0].class.contents); ASSERT_EQ('a', t.contents[0].contents[0].class.contents[0]); regex_free_children(&t); } static void caret_a_in_brackets_parses_as_negated_class(void) { regex_t t; const int result = PARSE_EXPR_STRING("[^a]", &t); ASSERT_NE(-1, result); ASSERT_EQ(1, t.count); ASSERT_NOT_NULL(t.contents); ASSERT_EQ(1, t.contents[0].count); ASSERT_EQ(REGEX_QUANTIFIER_NONE, t.contents[0].contents[0].quantifier); ASSERT_EQ(REGEX_TERM_CLASS, t.contents[0].contents[0].type); ASSERT_TRUE(t.contents[0].contents[0].class.negated); ASSERT_EQ(1, t.contents[0].contents[0].class.count); ASSERT_NOT_NULL(t.contents[0].contents[0].class.contents); ASSERT_EQ('a', t.contents[0].contents[0].class.contents[0]); regex_free_children(&t); } int main(void) { TESTING_BEGIN(); a_has_1_alternative(); a_pipe_b_has_2_alternatives(); a_pipe_b_pipe_c_has_3_alternatives(); a_is_parsed_as_unquantified_literal(); b_is_parsed_as_unquantified_literal(); abc_is_parsed_as_sequence_of_unquantified_literals(); dot_is_parsed_as_unquantified_wildcard_term(); backslash_dot_is_parsed_as_unquantified_literal(); backslash_backslash_is_parsed_as_unquantified_literal(); a_pipe_b_in_parens_is_parsed_as_subexpr_term(); a_in_parens_b_is_parsed_as_sequence_with_subexpr_term(); dot_star_is_parsed_as_star_quantified_wildcard(); dot_plus_is_parsed_as_plus_quantified_wildcard(); dot_question_mark_is_parsed_as_qmrk_quantified_wildcard(); a_in_brackets_is_parsed_as_class_containing_only_a(); caret_a_in_brackets_parses_as_negated_class(); return TESTING_END(); }