bitwalker / combine

A parser combinator library for Elixir projects
MIT License
197 stars 19 forks source link

Missing sequential operations? #45

Open luc-tielen opened 6 years ago

luc-tielen commented 6 years ago

Might have missed this, but the library seems to be missing a feature for chaining sequential operations? Something along the lines of an and_then function/parser?

The parser would take as input the parser to chain a sequential computation with; and a function that would take the results of previously said parser, and returns another parser for further parsing.

This could be for example useful when later parsed input depends on earlier parsed input. e.g. XML: checking if closing tag is same as opening tag.

Some pseudo-code (out of a lib I'm working on atm) that hopefully showcases the use-case where this could be used, closing_tag is a helper function that returns a parser based on a string input argument (the opening tag):

def tag_with_content_parser() do
    tag_with_attributes = sequence([tag(), many(attribute())])
    between(char("<"), tag_with_attrs, char(">"))
    |> and_then(fn [tag, attributes] ->
        sequence([value_parser(), ignore(closing_tag(tag))])
        |> map(fn [inner_contents] ->
            %XML.Tag{name: tag, attributes: attributes, value: inner_contents}
        end)
    end)
end

Side note: in Haskell this kind of function is heavily used when utilizing the monad interface of the parser type, a.k.a. the >>=/bind/flat_map operator.

For now, I will do it with a work-around, but this would be a very powerful feature to have since it allows specifying dependencies between multiple parsing steps.