Incorrectly set furthest value in lookahead?
See original GitHub issueFirst, thank you for your work on this library. It’s been a real pleasure to work with the last few days and really just astonishingly easy. However, I’ve hit a small hiccup I was hoping to get some help with.
I’m trying to define a combinator to parse the same input with two different parsers, failing if either fails, succeeding only if both succeed, and keeping only the second result. A &&
for parsers, basically (apologies if this already exists in the API and I just missed it).
I had hoped to implement this as const both = (parser1, parser2) => P.lookahead(parser1).chain(() => parser2)
or just P.lookahead(parser1).then(parser2)
, so I could use it something like
const FileParser = both(
P.regex(/[^\n]/).times(94).skip(P.end).many()
.desc('all lines of 94 characters'),
<long involved parser that seems to work fine alone>
);
This works just fine if both succeed or the first fails, but they eat the details of any failure produced by parser2
. If parser1
succeeds and parser2
fails, parser produced by both
will fail, but the final result will have the expected
array of the first parser and it loses the much-more-informative error of the second parser.
On investigation, I found that mergeReplies
was preferring parser1
’s result data because the parser produced by lookahead(x)
keeps whatever furthest
value was generated by x
. Still trying to grok the library internals, but either of the following get me the behavior I’m looking for
const both = (parser1, parser2) => (
P.Parser((input, i) => {
const result1 = parser1.parse(input);
return !result1.status
? P.makeFailure(result1.index.offset, result1.expected)
: P.makeSuccess(i, '');
})
.then(parser2)
);
// in parsimmon.js
function lookahead(x) {
if (isParser(x)) {
return Parsimmon(function(input, i) {
var result = x._(input, i);
result.index = i;
result.value = "";
result.furthest = -1; // Adding this here
return result;
});
} else if (typeof x === "string") {
......
So a couple questions. Am I understanding the internals or API here correctly? If so, should lookahead be setting furthest
manually to -1, or be returning a makeSuccess()?
Issue Analytics
- State:
- Created 3 years ago
- Comments:8 (1 by maintainers)
Top GitHub Comments
Thanks for the comment @anko, always nice to see you in these Parsimmon threads 😃
@tstodter Thanks for the kind words! I would definitely suggest using
lookahead
combined withthen
as @anko suggested. Also, you have a missing detail in your “all lines are 94 characters” parser. You need to add.then(P.eof)
to test that you hit the end of the file..many()
matches ZERO or more times, so if this parser fails to parse, it will just parse zero times and succeed.I think I see what you’re mentioning about the
result.furthest = -1
thing… I’ll do some investigation on this and see what I find out.I made an example here https://runkit.com/wavebeem/parsimmon-issues-296/5.0.0 and I was surprised by the 2nd output… I think you may be correct and this might be a bug.
and yeah, “fixing” this should only change the error messages, but i found lots of tests that returned empty (!!) “expected” arrays for parse failures, which is clearly not a good thing