Skip to content

Commit

Permalink
Add Dot combinator
Browse files Browse the repository at this point in the history
  • Loading branch information
evansmal committed Aug 30, 2023
1 parent 655b863 commit 933ccd4
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ using Expression = std::variant<Box<struct Sequence>,
Box<struct ZeroOrMore>,
Box<struct And>,
Box<struct Not>,
struct Dot,
struct Range,
struct Literal,
struct Identifier>;
Expand All @@ -43,6 +44,11 @@ struct Range
std::string end;
};

struct Dot
{
Dot() = default;
};

struct Optional
{
Optional(Expression child) : child{std::move(child)} {}
Expand Down
14 changes: 14 additions & 0 deletions src/combinator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,20 @@ auto Not(const Parser &parser) -> Parser
};
}

auto Dot() -> Parser
{
return [](const std::string &input)
{
if (input.empty())
{
return Result{Failure{{"Dot"}}};
}
std::string rest{input.begin() + 1, input.end()};
Terminal terminal{std::string(input.begin(), input.begin() + 1)};
return Result{Success{{terminal}, rest}};
};
}

auto Definition(const Parser &parser, const std::string &type) -> Parser
{
return [parser, type](const std::string &input)
Expand Down
2 changes: 2 additions & 0 deletions src/combinator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ auto And(const Parser &parser) -> Parser;

auto Not(const Parser &parser) -> Parser;

auto Dot() -> Parser;

auto Definition(const Parser &parser, const std::string &type) -> Parser;
4 changes: 4 additions & 0 deletions src/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ auto EmitExpression(const ast::Expression &expression, Collection &collection) -
}
return Alternative(parsers);
}
else if constexpr (std::is_same_v<T, ast::Dot>)
{
return Dot();
}
else if constexpr (std::is_same_v<T, ast::Literal>)
{
return Literal(expression.value);
Expand Down
26 changes: 24 additions & 2 deletions tests/combinator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ TEST_CASE("Ranges are parsed", "[Range]")
SECTION("Expect failure") { REQUIRE_NOTHROW(UnwrapFailure(Range("0", "1")("2"))); }
}

TEST_CASE("Dot is parsed", "[Dot]")
{
SECTION("Handle single values")
{
{
auto res = UnwrapSuccess(Dot()("a"));
REQUIRE(!res.node.empty());
REQUIRE(res.remainder.empty());
REQUIRE(UnwrapTerminal(res.node[0]).value == "a");
}
}
}

TEST_CASE("Sequence parsers", "[Sequence]")
{
SECTION("Parse sequence of literals")
Expand Down Expand Up @@ -249,14 +262,23 @@ TEST_CASE("Definition parser", "[Definition]")
SECTION("Parse definitions")
{
{
auto res = UnwrapSuccess(Definition(Literal("0"), "ZERO")("0"));
auto res = UnwrapSuccess(Definition(Literal("0"), "Zero")("0"));
REQUIRE(res.node.size() == 1);
REQUIRE(res.remainder.empty());
REQUIRE(UnwrapNonTerminal(res.node[0]).children.size() == 1);
REQUIRE(UnwrapNonTerminal(res.node[0]).type == "ZERO");
REQUIRE(UnwrapNonTerminal(res.node[0]).type == "Zero");
REQUIRE(UnwrapTerminal(UnwrapNonTerminal(res.node[0]).children[0]).value ==
"0");
}
{
auto res = UnwrapSuccess(Definition(ZeroOrMore(Dot()), "All")("123456789"));
REQUIRE(res.node.size() == 1);
REQUIRE(res.remainder.empty());
REQUIRE(UnwrapNonTerminal(res.node[0]).children.size() == 9);
REQUIRE(UnwrapNonTerminal(res.node[0]).type == "All");
REQUIRE(UnwrapTerminal(UnwrapNonTerminal(res.node[0]).children[0]).value ==
"1");
}
{
auto parser =
Definition(Sequence({OneOrMore(Literal("0")), OneOrMore(Literal("1"))}),
Expand Down

0 comments on commit 933ccd4

Please sign in to comment.