Skip to content

Commit

Permalink
Merge pull request #154 from /issues/150
Browse files Browse the repository at this point in the history
Fixes #150; adds notFollowedBy
  • Loading branch information
Brian Mock committed May 19, 2017
2 parents de7c923 + 899239c commit 8c1d55d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
8 changes: 8 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ Like `Parsimmon.regexp(regexp)`, but yields only the text in the specific regexp

This is an alias for `Parsimmon.regexp`.

## Parsimmon.notFollowedBy(parser)

Parses using `parser`, but does not consume what it parses. Yields an empty string if the parser *does not match* the input. Otherwise it fails.

## Parsimmon.lookahead(parser)

Parses using `parser`, but does not consume what it parses. Yields an empty string.
Expand Down Expand Up @@ -482,6 +486,10 @@ var parserA = p1.skip(p2); // is equivalent to...
var parserB = Parsimmon.seqMap(p1, p2, function(x1, x2) { return x1; });
```

## parser.notFollowedBy(anotherParser)

Returns a parser that looks for anything but whatever `anotherParser` wants to parse, and does not consume it. Yields the same result as `parser`. Equivalent to `parser.skip(Parsimmon.notFollowedBy(anotherParser))`.

## parser.lookahead(anotherParser)

Returns a parser that looks for whatever `anotherParser` wants to parse, but does not consume it. Yields the same result as `parser`. Equivalent to `parser.skip(Parsimmon.lookahead(anotherParser))`.
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## version 1.3.0 (2017-??-??)

* Adds `Parsimmon.notFollowedBy(parser)`
* Adds `parser.notFollowedBy(anotherParser)`

## version 1.2.0 (2016-12-22)

* Adds `Parsimmon.lookahead(parser)`
Expand Down
17 changes: 17 additions & 0 deletions src/parsimmon.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@
_.lookahead = function(x) {
return this.skip(lookahead(x));
};

_.notFollowedBy = function(x) {
return this.skip(notFollowedBy(x));
};

_.desc = function(expected) {
var self = this;
return Parsimmon(function(input, i) {
Expand Down Expand Up @@ -517,6 +522,17 @@
throw new Error('not a string, regexp, or parser: ' + x);
}

function notFollowedBy(parser) {
assertParser(parser);
return Parsimmon(function(input, i) {
var result = parser._(input, i);
var text = input.slice(i, result.index);
return result.status
? makeFailure(i, 'not "' + text + '"')
: makeSuccess(i, null);
});
}

var any = Parsimmon(function(input, i) {
if (i >= input.length) {
return makeFailure(i, 'any character');
Expand Down Expand Up @@ -666,6 +682,7 @@
Parsimmon.letter = letter;
Parsimmon.letters = letters;
Parsimmon.lookahead = lookahead;
Parsimmon.notFollowedBy = notFollowedBy;
Parsimmon.makeFailure = makeFailure;
Parsimmon.makeSuccess = makeSuccess;
Parsimmon.noneOf = noneOf;
Expand Down
36 changes: 34 additions & 2 deletions test/parsimmon.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ suite('parser', function() {
var lazy = Parsimmon.lazy;
var fail = Parsimmon.fail;
var lookahead = Parsimmon.lookahead;
var notFollowedBy = Parsimmon.notFollowedBy;

function equivalentParsers(p1, p2, inputs) {
for (var i = 0; i < inputs.length; i++) {
Expand Down Expand Up @@ -121,6 +122,37 @@ suite('parser', function() {
assert.deepEqual(answer, expectation);
});

suite('Parsimmon.notFollowedBy', function() {
test('fails when its parser argument matches', function() {
var weirdParser = string('dx');
var parser = seq(
string('abc'),
notFollowedBy(weirdParser).result('NOT USED'),
string('dx')
);
var answer = parser.parse('abcdx');
assert.deepEqual(answer.expected, ['not "dx"']);
});
test('does not consume from its input', function() {
var weirdParser = string('Q');
var parser = seq(
string('abc'),
notFollowedBy(weirdParser),
string('d')
);
var answer = parser.parse('abcd');
assert.deepEqual(answer.value, ['abc', null, 'd']);
});
test('can be chained from prototype', function() {
var parser = seq(
string('abc').notFollowedBy(string('Q')),
string('d')
);
var answer = parser.parse('abcd');
assert.deepEqual(answer.value, ['abc', 'd']);
});
});

suite('Parsimmon.lookahead', function() {
test('should handle a string', function() {
lookahead('');
Expand Down Expand Up @@ -225,7 +257,7 @@ suite('parser', function() {
var parser =
seq(
string('('),
regex(/[^\)]/).many().map(function(xs) {
regex(/[^)]/).many().map(function(xs) {
return xs.join('');
}),
string(')')
Expand All @@ -245,7 +277,7 @@ suite('parser', function() {
line: 1,
column: 8
},
expected: ['\')\'', '/[^\\)]/']
expected: ['\')\'', '/[^)]/']
}
);

Expand Down

0 comments on commit 8c1d55d

Please sign in to comment.