Fix error messages in certain cases with trailing input

In case the generated parser parsed successfully part of input and left
some input unparsed (trailing input), the error message produced was
sometimes wrong. The code worked correctly only if there were no match
failures in the successfully parsed part (highly unlikely).

This commit fixes things by explicitly triggering a match failure with the
following expectation at the end of the successfully parsed part of the
input:

  peg$fail({ type: "end", description: "end of input" });

This change also made it possible to simplify the |buildMessage|
function, which can now ignore the case of no expectations.

Fixes #119.
redux
David Majda 11 years ago
parent 44e03187a7
commit a56d3ac94f

@ -902,28 +902,18 @@ module.exports = function(ast, options) {
' .replace(/[\\u1080-\\uFFFF]/g, function(ch) { return \'\\\\u\' + hex(ch); });',
' }',
'',
' var expectedDescs, expectedDesc, foundDesc, i;',
' var expectedDescs = new Array(expected.length),',
' expectedDesc, foundDesc, i;',
'',
' switch (expected.length) {',
' case 0:',
' expectedDesc = "end of input";',
' break;',
'',
' case 1:',
' expectedDesc = expected[0].description;',
' break;',
'',
' default:',
' expectedDescs = new Array(expected.length);',
'',
' for (i = 0; i < expected.length; i++) {',
' expectedDescs[i] = expected[i].description;',
' }',
' for (i = 0; i < expected.length; i++) {',
' expectedDescs[i] = expected[i].description;',
' }',
'',
' expectedDesc = expectedDescs.slice(0, -1).join(", ")',
' expectedDesc = expected.length > 1',
' ? expectedDescs.slice(0, -1).join(", ")',
' + " or "',
' + expectedDescs[expected.length - 1];',
' }',
' + expectedDescs[expected.length - 1]',
' : expectedDescs[0];',
'',
' foundDesc = found ? "\\"" + stringEscape(found) + "\\"" : "end of input";',
'',
@ -975,11 +965,11 @@ module.exports = function(ast, options) {
' if (peg$result !== peg$FAILED && peg$currPos === input.length) {',
' return peg$result;',
' } else {',
' throw peg$buildException(',
' null,',
' peg$maxFailExpected,',
' Math.max(peg$currPos, peg$maxFailPos)',
' );',
' if (peg$result !== peg$FAILED && peg$currPos < input.length) {',
' peg$fail({ type: "end", description: "end of input" });',
' }',
'',
' throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);',
' }',
' }',
'',

@ -465,28 +465,18 @@ module.exports = (function() {
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
var expectedDescs, expectedDesc, foundDesc, i;
var expectedDescs = new Array(expected.length),
expectedDesc, foundDesc, i;
switch (expected.length) {
case 0:
expectedDesc = "end of input";
break;
case 1:
expectedDesc = expected[0].description;
break;
default:
expectedDescs = new Array(expected.length);
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
expectedDesc = expectedDescs.slice(0, -1).join(", ")
expectedDesc = expected.length > 1
? expectedDescs.slice(0, -1).join(", ")
+ " or "
+ expectedDescs[expected.length - 1];
}
+ expectedDescs[expected.length - 1]
: expectedDescs[0];
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
@ -2792,11 +2782,11 @@ module.exports = (function() {
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
throw peg$buildException(
null,
peg$maxFailExpected,
Math.max(peg$currPos, peg$maxFailPos)
);
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail({ type: "end", description: "end of input" });
}
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
}
}

@ -843,7 +843,9 @@ describe("generated parser", function() {
it("reports expectations correctly with no alternative", function() {
var parser = PEG.buildParser('start = ', options);
expect(parser).toFailToParse("a", { expected: [] });
expect(parser).toFailToParse("a", {
expected: [{ type: "end", description: "end of input" }]
});
});
it("reports expectations correctly with one alternative", function() {

Loading…
Cancel
Save