diff --git a/libs/parser/include/psemek/parser/combinators.hpp b/libs/parser/include/psemek/parser/combinators.hpp index 0cacc527..5dc7cacc 100644 --- a/libs/parser/include/psemek/parser/combinators.hpp +++ b/libs/parser/include/psemek/parser/combinators.hpp @@ -84,6 +84,49 @@ namespace psemek::parser return res; } + template + struct recursive_helper + { + using P = decltype(std::declval()(std::declval>())); + P p; + + recursive_helper(Gen && gen) + : p(std::forward(gen)(parser_ref{this})) + {} + + template + result apply(Buffer & buf) const + { + return p.apply(buf); + } + + R parse(std::string_view text) const + { + return p.parse(text); + } + }; + + template + struct recursive_impl + { + std::unique_ptr> p; + + recursive_impl(Gen && gen) + : p(std::make_unique>(std::forward(gen))) + {} + + template + result apply(Buffer & buf) const + { + return p->apply(buf); + } + + R parse(std::string_view text) const + { + return p->parse(text); + } + }; + } template @@ -261,4 +304,10 @@ namespace psemek::parser return fold(std::forward

(p), [](auto const &, auto const &){ return skip_token{}; }, skip_token{}); } + template + auto recursive(Gen && gen) + { + return detail::recursive_impl(std::forward(gen)); + } + } diff --git a/libs/parser/include/psemek/parser/parser.hpp b/libs/parser/include/psemek/parser/parser.hpp index 8e9c62bf..749d3390 100644 --- a/libs/parser/include/psemek/parser/parser.hpp +++ b/libs/parser/include/psemek/parser/parser.hpp @@ -105,6 +105,23 @@ namespace psemek::parser } }; + template + struct parser_ref + { + P * p; + + template + auto apply(Buffer & buf) const + { + return p->apply(buf); + } + + auto parse(std::string_view text) const + { + return p->parse(text); + } + }; + } struct error