Skip to content

How to get terminator of AtLeastOnceUntil without lookahead and parsing twice? #121

@chyyran

Description

@chyyran

I'm trying to port a parser written with nom in Rust to a C# parser with Pidgin. There are some cases where I need the result of a terminator from AtLeastOnceUntil. With nom, I can extract both the first result, and the terminator like so

let (input, (title, version)) = take_up_to(
        alt((
            preceded(char(' '), parse_version_string).map(|t| Some(t)),
            peek(alt((char('('), char('[')))).map(|_| None)))
    )(input)?;

Somewhat equivalently I've written up this parser with Pidgin

from title in Any.AtLeastOnceUntil(Lookahead(
           Try(Char(' ').Before(ParseVersionString)).Or(
               Try(Char('(').Or(Char('[')))))).Select(string.Concat)
from version in Char(' ').Then(ParseVersionString).Optional()
select (title, version.Match(v => new RomTag[] { v }, () => Enumerable.Empty<RomTag>()));

While both of the terminator parsers have to run O(t) iterations where t is the length of title, it doesn't need to re-parse the version in the Rust version. Is it possible to achieve this with Pidgin or is this pretty much the best way to do it?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions