Skip to content

Commit

Permalink
match: support nonterminal for left_recursion.
Browse files Browse the repository at this point in the history
  • Loading branch information
soasme committed Aug 26, 2021
1 parent c404d33 commit 01f94c2
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
9 changes: 5 additions & 4 deletions peppa.c
Original file line number Diff line number Diff line change
Expand Up @@ -2277,12 +2277,13 @@ match_left_recursion(P4_Source* s, P4_Expression* e) {
if (is_non_terminal(e) && toktmp->head == toktmp->tail && toktmp->head != NULL) {
toklhs = toktmp->head;
toktmp->head = NULL;
toktmp->tail = NULL;
P4_DeleteNode(s->grammar, toktmp);
} else {
/* on next loop, we will use the parsed inputs as lhs and
* attempt to match rhs, if any. */
toklhs = toktmp;
}

/* on next loop, we will use the parsed inputs as lhs and
* attempt to match rhs, if any. */
toklhs = toktmp;
} while (true);

return toklhs;
Expand Down
58 changes: 58 additions & 0 deletions tests/test_left_recursion.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,63 @@ void test_match_left_recursion_spaced(void) {
P4_DeleteGrammar(grammar);
}

/**
* Grammar:
* @nonterminal entry = A | entry ("++" / minus A);
* A = "a";
* minus = "-";
* Input:
* a++
*/
void test_match_left_recursion_nonterminal(void) {
P4_Grammar* grammar = P4_CreateGrammar();
TEST_ASSERT_NOT_NULL(grammar);
TEST_ASSERT_EQUAL(
P4_Ok,
P4_AddLeftRecursion(grammar, "entry",
P4_CreateReference("A"),
P4_CreateChoiceWithMembers(2,
P4_CreateLiteral("++", true),
P4_CreateSequenceWithMembers(2,
P4_CreateReference("minus"),
P4_CreateReference("A")
)
)
)
);
TEST_ASSERT_EQUAL(P4_Ok, P4_SetGrammarRuleFlag(grammar, "entry", P4_FLAG_NON_TERMINAL));
TEST_ASSERT_EQUAL(
P4_Ok,
P4_AddLiteral(grammar, "A", "a", true)
);
TEST_ASSERT_EQUAL(
P4_Ok,
P4_AddLiteral(grammar, "minus", "-", true)
);
P4_Source* source = P4_CreateSource("a++-a", "entry");
TEST_ASSERT_NOT_NULL(source);
TEST_ASSERT_EQUAL(
P4_Ok,
P4_Parse(grammar, source)
);

P4_Node* node = P4_GetSourceAst(source);
TEST_ASSERT_NOT_NULL(node);
ASSERT_EQUAL_NODE_STRING("a++-a", node);

TEST_ASSERT_NOT_NULL(node->head);
ASSERT_EQUAL_NODE_STRING("a", node->head); /* ++ is dropped by nonterminal. */

TEST_ASSERT_NOT_NULL(node->head->next);
ASSERT_EQUAL_NODE_STRING("-", node->head->next);

TEST_ASSERT_NOT_NULL(node->tail);
ASSERT_EQUAL_NODE_STRING("a", node->tail);

P4_DeleteSource(source);
P4_DeleteGrammar(grammar);
}

/** Because lifted eliminates the hierarchy of left recursion.
* which in essence makes the expression become (lhs rhs*).
* */
Expand Down Expand Up @@ -280,6 +337,7 @@ int main(void) {
RUN_TEST(test_match_left_recursion_references);
RUN_TEST(test_match_left_recursion_sequence_on_rhs);
RUN_TEST(test_match_left_recursion_spaced);
RUN_TEST(test_match_left_recursion_nonterminal);
RUN_TEST(test_left_recursion_cannot_use_with_lifted);

return UNITY_END();
Expand Down

0 comments on commit 01f94c2

Please sign in to comment.