Skip to content

Commit

Permalink
Merge pull request #247 from avast/fix/empty-alt-group
Browse files Browse the repository at this point in the history
fix(parser): Fixed parsing of empty alternation groups (#193)
  • Loading branch information
metthal committed Jun 12, 2023
2 parents aa06dd4 + e7742d7 commit 45b82b2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/parser/parser_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,12 @@ void ParserDriver::defineGrammar()
std::shared_ptr<RegexpUnit> concat = std::make_shared<RegexpConcat>(args[2].getMultipleRegexpUnits());
return std::make_shared<RegexpOr>(std::move(arg), std::move(concat));
})
.production("regexp_or", "REGEXP_OR", [](auto&& args) -> Value {
// Special case in which we end alternation with empty string (like /(a|b|)/) which needs to be handled this way
// otherwise the grammar produces shift-reduce conflicts
std::shared_ptr<RegexpUnit> arg = std::move(args[0].getRegexpUnit());
return std::make_shared<RegexpOr>(std::move(arg), std::make_shared<RegexpText>(""));
})
;

_parser.rule("regexp_concat") // vector<shared_ptr<RegexpUnit>>
Expand Down
34 changes: 34 additions & 0 deletions tests/cpp/parser_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,40 @@ rule regexp_with_unescaped_square_brackets_inside_class
EXPECT_EQ(input_text, driver.getParsedFile().getTextFormatted());
}

TEST_F(ParserTests,
RegexpWithEmptyAlternationGroupWorks) {
prepareInput(
R"(
rule regexp_with_empty_alternation_group
{
strings:
$1 = /(a|b|)/
condition:
all of them
}
)");

EXPECT_TRUE(driver.parse(input));
ASSERT_EQ(1u, driver.getParsedFile().getRules().size());

const auto& rule = driver.getParsedFile().getRules()[0];
EXPECT_EQ("regexp_with_empty_alternation_group", rule->getName());
EXPECT_EQ(Rule::Modifier::None, rule->getModifier());

auto strings = rule->getStrings();
ASSERT_EQ(1u, strings.size());

auto regexp1 = strings[0];
EXPECT_TRUE(regexp1->isRegexp());
EXPECT_EQ("$1", regexp1->getIdentifier());
EXPECT_EQ(R"(/(a|b|)/)", regexp1->getText());

EXPECT_EQ("all", rule->getCondition()->getFirstTokenIt()->getPureText());
EXPECT_EQ("them", rule->getCondition()->getLastTokenIt()->getPureText());

EXPECT_EQ(input_text, driver.getParsedFile().getTextFormatted());
}

TEST_F(ParserTests,
InvalidCuckooRuleAccessTokenStream) {
prepareInput(
Expand Down

0 comments on commit 45b82b2

Please sign in to comment.