Support passing custom location info to "error" and "expected"

Based on a pull request by Konstantin (@YemSalat):

  https://github.com/pegjs/pegjs/pull/391

Resolves #390.
redux
David Majda 8 years ago
parent da2378d887
commit ce44c62f14

@ -403,13 +403,16 @@ using the `return` statement. This value is considered match result of the
preceding expression. preceding expression.
To indicate an error, the code inside the action can invoke the `expected` To indicate an error, the code inside the action can invoke the `expected`
function, which makes the parser throw an exception. The function takes one function, which makes the parser throw an exception. The function takes two
parameter — a description of what was expected at the current position. This parameters — a description of what was expected at the current position and
description will be used as part of a message of the thrown exception. optional location information (the default is what `location` would return — see
below). The description will be used as part of a message of the thrown
exception.
The code inside an action can also invoke the `error` function, which also makes The code inside an action can also invoke the `error` function, which also makes
the parser throw an exception. The function takes one parameter — an error the parser throw an exception. The function takes two parameters — an error
message. This message will be used by the thrown exception. message and optional location information (the default is what `location` would
return — see below). The message will be used by the thrown exception.
The code inside the action can access all variables and functions defined in the The code inside the action can access all variables and functions defined in the
initializer at the beginning of the grammar. Curly braces in the action code initializer at the beginning of the grammar. Curly braces in the action code

@ -967,20 +967,20 @@ function generateJS(ast, options) {
' return peg$computeLocation(peg$savedPos, peg$currPos);', ' return peg$computeLocation(peg$savedPos, peg$currPos);',
' }', ' }',
'', '',
' function expected(description) {', ' function expected(description, location) {',
' location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)',
'',
' throw peg$buildException(', ' throw peg$buildException(',
' null,', ' null,',
' [{ type: "other", description: description }],', ' [{ type: "other", description: description }],',
' peg$computeLocation(peg$savedPos, peg$currPos)', ' location',
' );', ' );',
' }', ' }',
'', '',
' function error(message) {', ' function error(message, location) {',
' throw peg$buildException(', ' location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)',
' message,', '',
' null,', ' throw peg$buildException(message, null, location);',
' peg$computeLocation(peg$savedPos, peg$currPos)',
' );',
' }', ' }',
'', '',
' function peg$computePosDetails(pos) {', ' function peg$computePosDetails(pos) {',

@ -416,20 +416,20 @@ module.exports = (function() {
return peg$computeLocation(peg$savedPos, peg$currPos); return peg$computeLocation(peg$savedPos, peg$currPos);
} }
function expected(description) { function expected(description, location) {
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
throw peg$buildException( throw peg$buildException(
null, null,
[{ type: "other", description: description }], [{ type: "other", description: description }],
peg$computeLocation(peg$savedPos, peg$currPos) location
); );
} }
function error(message) { function error(message, location) {
throw peg$buildException( location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
message,
null, throw peg$buildException(message, null, location);
peg$computeLocation(peg$savedPos, peg$currPos)
);
} }
function peg$computePosDetails(pos) { function peg$computePosDetails(pos) {

@ -1211,35 +1211,79 @@ describe("generated parser behavior", function() {
}); });
}); });
it("|expected| terminates parsing and throws an exception", function() { describe("|expected|", function() {
var parser = PEG.buildParser( it("terminates parsing and throws an exception", function() {
'start = "a" { expected("a"); }', var parser = PEG.buildParser(
options 'start = "a" { expected("a"); }',
); options
);
expect(parser).toFailToParse("a", { expect(parser).toFailToParse("a", {
message: 'Expected a.', message: 'Expected a.',
expected: [{ type: "other", description: "a" }], expected: [{ type: "other", description: "a" }],
location: { location: {
start: { offset: 0, line: 1, column: 1 }, start: { offset: 0, line: 1, column: 1 },
end: { offset: 1, line: 1, column: 2 } end: { offset: 1, line: 1, column: 2 }
} }
});
});
it("allows to set custom location info", function() {
var parser = PEG.buildParser([
'start = "a" {',
' expected("a", {',
' start: { offset: 1, line: 1, column: 2 },',
' end: { offset: 2, line: 1, column: 3 }',
' });',
'}'
].join("\n"), options);
expect(parser).toFailToParse("a", {
message: 'Expected a.',
expected: [{ type: "other", description: "a" }],
location: {
start: { offset: 1, line: 1, column: 2 },
end: { offset: 2, line: 1, column: 3 }
}
});
}); });
}); });
it("|error| terminates parsing and throws an exception", function() { describe("|error|", function() {
var parser = PEG.buildParser( it("terminates parsing and throws an exception", function() {
'start = "a" { error("a"); }', var parser = PEG.buildParser(
options 'start = "a" { error("a"); }',
); options
);
expect(parser).toFailToParse("a", { expect(parser).toFailToParse("a", {
message: "a", message: "a",
expected: null, expected: null,
location: { location: {
start: { offset: 0, line: 1, column: 1 }, start: { offset: 0, line: 1, column: 1 },
end: { offset: 1, line: 1, column: 2 } end: { offset: 1, line: 1, column: 2 }
} }
});
});
it("allows to set custom location info", function() {
var parser = PEG.buildParser([
'start = "a" {',
' error("a", {',
' start: { offset: 1, line: 1, column: 2 },',
' end: { offset: 2, line: 1, column: 3 }',
' });',
'}'
].join("\n"), options);
expect(parser).toFailToParse("a", {
message: "a",
expected: null,
location: {
start: { offset: 1, line: 1, column: 2 },
end: { offset: 2, line: 1, column: 3 }
}
});
}); });
}); });
}); });

Loading…
Cancel
Save