Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choice parser behavior #162

Closed
f3ath opened this issue Dec 25, 2023 · 2 comments
Closed

Choice parser behavior #162

f3ath opened this issue Dec 25, 2023 · 2 comments
Assignees
Labels

Comments

@f3ath
Copy link
Contributor

f3ath commented Dec 25, 2023

Hi @renggli , here's an issue I'm struggling with. There's a certain set of repeated patterns in which I want to attempt to detect a stricter subset first, and then fall back to a more generic one. Let's say I want to first detect a string of one or more uppercase A s or otherwise fall back to a string of case-insensitive as, e.g.

    final uppercase = char('A').plus().map((_) => 'success');
    final anycase = charIgnoringCase('A').plus().map((_) => 'fallback');
    final parser = [uppercase, anycase].toChoiceParser().end();
    print(parser.parse('AAAA')); // "success", as expected
    print(parser.parse('aaaAAaaa')); // "fallback", as expected
    print(parser.parse('AAaaaA')); // I expect "fallback", but getting "Failure[1:3]: end of input expected"

On the last print() I want to get a "fallback" as well. What's the right way to achieve this?

@renggli renggli self-assigned this Dec 25, 2023
@renggli
Copy link
Member

renggli commented Dec 25, 2023

You get this behavior in your last example because your uppercase parser succeeds consuming the two first uppercase A and the choice picks this result as a success.

In your example you can fix this by pulling up the .end() predicate into the choice:

final uppercase = char('A').plus().map((_) => 'success');
final anycase = charIgnoringCase('A').plus().map((_) => 'fallback');
final parser = [uppercase.end(), anycase.end()].toChoiceParser();

In a more general case you can say that uppercase is not followed by an anycase-character, i.e. something along the lines of:

final uppercase = char('A').plus().map((_) => 'success');
final anycase = charIgnoringCase('A').plus().map((_) => 'fallback');
final parser = [uppercase.skip(after: charIgnoringCase('A').not()), anycase].toChoiceParser().end();

renggli added a commit that referenced this issue Dec 25, 2023
@f3ath
Copy link
Contributor Author

f3ath commented Dec 25, 2023

Thank you, the general case is what I was looking for!

@f3ath f3ath closed this as completed Dec 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants