joemalle / limn

A tiny parser designed to compile quickly
Boost Software License 1.0
2 stars 1 forks source link

bug in alternative rules, the string never get rewind #6

Closed asmwarrior closed 1 year ago

asmwarrior commented 1 year ago
        template <typename Left, typename Right>
        struct alt_ final : public impl::parser_base<alt_<Left, Right>> {
            constexpr explicit alt_(Left&& left, Right&& right) noexcept
                : left(std::forward<Left>(left))
                , right(std::forward<Right>(right))
            {}

            constexpr inline bool visit(std::string_view& sv) const& noexcept {
                return left.visit(sv) || right.visit(sv);
            }

        private:
            Left left;
            Right right;
        };

If you look at this code, the sv get changed when running the left.visit(sv), and never get rewind, I think this should be a bug.

For testing the code:

auto callback_hello = [](const std::string_view&){
    std::cout << "I will be called even though I'm in an expression that later fails to match" << std::endl;
};

auto callback_universe = [](const std::string_view&){
    std::cout << "I will be called (which is probably expected)" << std::endl;
};

    parse(
        "hello universe",
        (lit_("hello")[callback_hello] >> lit_("world")) | (lit_("hello universe")[callback_universe]) >> end_
    );

It is strange that only the callback_hello function get called, not both. It is expected to call both.

asmwarrior commented 1 year ago

I think I have fixed this bug in the PR, but please note that restore a string and later recover it maybe cause some performance issue.

joemalle commented 1 year ago

this will not cause performance issues. string_views are tiny reference-types that just contain a pointer to the beginning of the view and a length. the actual string is owned by the user who calls parse