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

sepBy1 within possibly parses nothing #111

Open
devurandom opened this issue Oct 15, 2023 · 1 comment
Open

sepBy1 within possibly parses nothing #111

devurandom opened this issue Oct 15, 2023 · 1 comment

Comments

@devurandom
Copy link

devurandom commented Oct 15, 2023

Following code (with sepBy1 wrapped as needed to workaround #109):

import {
    optionalWhitespace,
    Parser,
    possibly,
    sepBy1 as _sepBy1,
    sequenceOf,
    str,
    whitespace
} from "arcsecond";

const sepBy1 = <S, T>(sep: Parser<S>, value: Parser<T>) =>
    _sepBy1(sep)(value) as Parser<T[]>;

const b = str("b")
const c = str("c")
const a1 = sequenceOf([
    str("a"),
    possibly(sequenceOf([whitespace, b])),
    possibly(sequenceOf([whitespace, c]))])
const a2 = sequenceOf([
    str("a"),
    possibly(sequenceOf([whitespace, sepBy1(optionalWhitespace, b)])),
    possibly(sequenceOf([whitespace, sepBy1(optionalWhitespace, c)]))])

export const parse1 = (input: string) => a1.run(input);
export const parse2 = (input: string) => a2.run(input);

parses the string "a b c" in the a1 variant, but not in the a2 variant:

❯ pnpm build

> arcsecond-repro3@0.1.0 build [REDACTED]/arcsecond-repro3
> tsc -p .

❯ node
Welcome to Node.js v18.17.1.
Type ".help" for more information.
> p = await import("./dist/parser.js?v1")
[Module: null prototype] {
  parse1: [Function: parse1],
  parse2: [Function: parse2]
}
> p.parse1("a b c")
{
  isError: false,
  result: [ 'a', [ ' ', 'b' ], [ ' ', 'c' ] ],
  index: 5,
  data: null
}
> p.parse2("a b c")
{ isError: false, result: [ 'a', null, null ], index: 1, data: null }

Please find a complete example in https://github.com/devurandom/arcsecond-issue-111-repro.

@devurandom
Copy link
Author

devurandom commented Oct 16, 2023

I found an implementation of sepBy1 that works:

import {
    coroutine,
    either,
    lookAhead,
    Parser,
    sequenceOf,
} from "arcsecond";

const sepBy1 = <T>(sep: Parser<string>, val: Parser<T>) =>
    coroutine((run) => {
        const results: T[] = [run(val)];

        const next = sequenceOf([sep, val])
        while (!run(either(lookAhead(next))).isError) {
            const [_, value] = run(next);
            results.push(value);
        }

        return results;
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant