Skip to content

Commit

Permalink
Merge pull request #256 from MrJohz/master
Browse files Browse the repository at this point in the history
Allow multiple expected values to be passed into desc and makeFailure calls
  • Loading branch information
Brian Mock committed Jun 16, 2018
2 parents 6690c37 + 7a9cee0 commit 11fb182
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 23 deletions.
6 changes: 4 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ To be used inside of `Parsimmon(fn)`. Generates an object describing how far the

## Parsimmon.makeFailure(furthest, expectation)

To be used inside of `Parsimmon(fn)`. Generates an object describing how far the unsuccessful parse went (`index`), and what kind of syntax it expected to see (`expectation`). See documentation for `Parsimmon(fn)`.
To be used inside of `Parsimmon(fn)`. Generates an object describing how far the unsuccessful parse went (`index`), and what kind of syntax it expected to see (`expectation`). The expected value may also be an array of different values. See documentation for `Parsimmon(fn)`.

## Parsimmon.isParser(obj)

Expand Down Expand Up @@ -961,7 +961,9 @@ Identifier.tryParse('hey');
## parser.desc(description)

Returns a new parser whose failure message is `description`. For example, `string('x').desc('the letter x')` will indicate that
`'the letter x'` was expected.
`'the letter x'` was expected. Alternatively, an array of failure messages can be passed, if the parser represents multiple
options. For example, `oneOf('abc').desc(['a', 'b', 'c'])` will indicate that any of 'a', 'b', or 'c' would be acceptable in
this case.

It is important to only add descriptions to "low-level" parsers; things like numbers and strings. If you add a description to *every* parser you write then generated error messages will not be very helpful when simple syntax errors occur.

Expand Down
28 changes: 21 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 14 additions & 4 deletions src/parsimmon.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,15 @@ function makeSuccess(index, value) {
}

function makeFailure(index, expected) {
if (!isArray(expected)) {
expected = [expected];
}
return {
status: false,
index: -1,
value: null,
furthest: index,
expected: [expected]
expected: expected
};
}

Expand Down Expand Up @@ -775,11 +778,14 @@ _.notFollowedBy = function(x) {
};

_.desc = function(expected) {
if (!isArray(expected)) {
expected = [expected];
}
var self = this;
return Parsimmon(function(input, i) {
var reply = self._(input, i);
if (!reply.status) {
reply.expected = [expected];
reply.expected = expected;
}
return reply;
});
Expand Down Expand Up @@ -923,15 +929,19 @@ function test(predicate) {
}

function oneOf(str) {
var expected = str.split("");
for (var idx = 0; idx < expected.length; idx++) {
expected[idx] = "'" + expected[idx] + "'";
}
return test(function(ch) {
return str.indexOf(ch) >= 0;
});
}).desc(expected);
}

function noneOf(str) {
return test(function(ch) {
return str.indexOf(ch) < 0;
});
}).desc("none of '" + str + "'");
}

function custom(parsingFunction) {
Expand Down
29 changes: 29 additions & 0 deletions test/core/desc.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,33 @@ suite("desc", function() {
expected: ["the letter y"]
});
});

test("allows multiple descriptions to be passed as an array", function() {
var x = Parsimmon.oneOf("xyz")
.desc(["x", "y", "z"])
.atLeast(1);
var y = Parsimmon.oneOf("abc").desc(["a", "b", "c"]);

var parser = x.then(y);

assert.deepEqual(parser.parse("~"), {
status: false,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ["x", "y", "z"]
});

assert.deepEqual(parser.parse("x"), {
status: false,
index: {
offset: 1,
line: 1,
column: 2
},
expected: ["a", "b", "c", "x", "y", "z"]
});
});
});
34 changes: 24 additions & 10 deletions test/core/makeFailure.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
"use strict";

test("Parsimmon.makeFailure", function() {
var furthest = 4444;
var expected = "waiting in the clock tower";
var result = Parsimmon.makeFailure(furthest, expected);
assert.deepEqual(result, {
status: false,
index: -1,
value: null,
furthest: furthest,
expected: [expected]
suite("Parsimmon.makeFailure", function() {
test("creates a failure result", function() {
var furthest = 4444;
var expected = "waiting in the clock tower";
var result = Parsimmon.makeFailure(furthest, expected);
assert.deepEqual(result, {
status: false,
index: -1,
value: null,
furthest: furthest,
expected: [expected]
});
});
test("creates a result with multiple expected values", function() {
var furthest = 4444;
var expected = ["once", "twice", "three times a lady"];
var result = Parsimmon.makeFailure(furthest, expected);
assert.deepEqual(result, {
status: false,
index: -1,
value: null,
furthest: furthest,
expected: expected
});
});
});

0 comments on commit 11fb182

Please sign in to comment.