joemalle / limn

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

Is it possible to add the action of a correct match? #1

Closed asmwarrior closed 1 year ago

asmwarrior commented 1 year ago

Hi, once a rule get matched, are there any way to add some code for the action, I mean I need to construct an ast from a correct parse, thanks.

BTW: your library is good, simple, and easy to read, thanks!

joemalle commented 1 year ago

Hi! I'm glad you like this library.

Unfortunately I don't think there's a way to run code when something matches. You could submit a PR to add such functionality or you might want to look into other libraries such as boost spirit.

asmwarrior commented 1 year ago

Hi, thanks for the reply.

I see there is a function operator []

    /// @brief The match operator
    /// @details This side-effect-only function copies the matched part of
    ///     input to its argument output.  If there is no match, then output
    ///     is unchanged.  For example, `(* lm::char_('a'))[output]` will match
    ///     any number of `a` characters in sequence, and it will copy that
    ///     sequence to the `std::string_view` `output`.
    ///
    ///     This is useful for getting the matched string out of the parser.
    ///     It's also sometimes useful for printf-debugging.
    ///
    ///     See tests.cpp or README.md for an example.
    ///
    /// @param[out] output The argument to receive the match portion.
    template <typename Base>
    constexpr inline auto impl::parser_base<Base>::operator[](std::string_view& ouput) const noexcept {
        return impl::match_<Base>(*static_cast<Base const*>(this), ouput);
    }

Do you think this is the way to implement such action?

I mean run a function in the []?

Thanks.

joemalle commented 1 year ago

Right now, it's not possible. You'd have to add another overload. Something like

    template <typename Base>
    constexpr inline auto impl::parser_base<Base>::operator[](std::function<void(const std::string_view&)> callback) const noexcept {
        return impl:: match_call_ <Base>(*static_cast<Base const*>(this), std::move(callback));
    }

....

        template <typename Base>
        struct match_call_ final : public impl::parser_base<match_<Base>> {
            constexpr explicit match_(Base base, std::function<void(const std::string_view&)> callback) noexcept
                : base(std::move(base))
                , callback(std::move(callback))
            {}

            constexpr inline bool visit(std::string_view& sv) const& noexcept {
                std::string_view save = sv;
                if (base.visit(sv)) {
                    callback(save.substr(0, save.size() - sv.size()));
                    return true;
                }
                return false;
            }

        private:
            Base base;
            std::function<void(const std::string_view&)> callback;
        };

I don't have time to add this properly (with comments/tests/etc) but feel free to go for it!

asmwarrior commented 1 year ago

Hi, many thanks for the reply and help.

I just follow the way your directed, and I have add such feature. Now, I have a PR created, can you have a look.

I have both code changes in the header file, and the tests.cpp file. Thanks.

EDIT: When running the test, it will print such matched content:

xyz
567