Improved & simplified error handling code.

redux
David Majda 14 years ago
parent b86a219c86
commit bddb65ab9b

@ -87,7 +87,7 @@ PEG.Parser.prototype = {
function buildExpectedFromMatchFailures(failures) { function buildExpectedFromMatchFailures(failures) {
switch (failures.length) { switch (failures.length) {
case 0: case 0:
return "nothing"; return "end of input";
case 1: case 1:
return failures[0].toString(); return failures[0].toString();
default: default:
@ -100,19 +100,13 @@ PEG.Parser.prototype = {
} }
} }
if (that._pos === 0) { var expected = buildExpectedFromMatchFailures(
var expected = buildExpectedFromMatchFailures( that._rightmostMatchFailures
that._rightmostMatchFailures );
); var pos = Math.max(that._pos, that._rightmostMatchFailuresPos);
var actual = that._rightmostMatchFailuresPos < that._input.length var actual = pos < that._input.length
? PEG.StringUtils.quote( ? PEG.StringUtils.quote(that._input.charAt(pos))
that._input.charAt(that._rightmostMatchFailuresPos) : "end of input";
)
: "end of input";
} else {
var expected = "end of input";
var actual = PEG.StringUtils.quote(that._input.charAt(that._pos));
}
return "Expected " + expected + " but " + actual + " found."; return "Expected " + expected + " but " + actual + " found.";
} }
@ -157,6 +151,33 @@ PEG.Parser.prototype = {
}; };
var result = this["_parse_" + this._startRule](initialContext); var result = this["_parse_" + this._startRule](initialContext);
/*
* The parser is now in one of the following three states:
*
* 1. The parser successfully parsed the whole input.
*
* - |result !== null|
* - |that._pos === input.length|
* - |that._rightmostMatchFailures.length| may or may not contain
* something
*
* 2. The parser successfully parsed only a part of the input.
*
* - |result !== null|
* - |that._pos < input.length|
* - |that._rightmostMatchFailures.length| may or may not contain
* something
*
* 3. The parser did not successfully parse any part of the input.
*
* - |result === null|
* - |that._pos === 0|
* - |that._rightmostMatchFailures.length| contains at least one failure
*
* All code following this comment (including called functions) must
* handle these states.
*/
if (result === null || this._pos !== input.length) { if (result === null || this._pos !== input.length) {
var errorPosition = computeErrorPosition(); var errorPosition = computeErrorPosition();
throw new PEG.Parser.SyntaxError( throw new PEG.Parser.SyntaxError(

@ -365,18 +365,25 @@ test("error messages", function() {
'Expected digits but end of input found.' 'Expected digits but end of input found.'
); );
var choiceParser = PEG.buildParser('start: "a" / "b" / "c"'); var choiceParser1 = PEG.buildParser('start: "a" / "b" / "c"');
doesNotParseWithMessage( doesNotParseWithMessage(
choiceParser, choiceParser1,
"def", "def",
'Expected "a", "b" or "c" but "d" found.' 'Expected "a", "b" or "c" but "d" found.'
); );
var choiceParser2 = PEG.buildParser('start: "a" "b" "c" / "a"');
doesNotParseWithMessage(
choiceParser2,
"abd",
'Expected "c" but "d" found.'
);
var emptyParser = PEG.buildParser('start: '); var emptyParser = PEG.buildParser('start: ');
doesNotParseWithMessage( doesNotParseWithMessage(
emptyParser, emptyParser,
"something", "something",
'Expected nothing but "s" found.' 'Expected end of input but "s" found.'
); );
}); });

Loading…
Cancel
Save