Skip to content

Commit

Permalink
Fixes state handling and adds more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Mock committed Jul 5, 2017
1 parent 97b27de commit 32316cf
Show file tree
Hide file tree
Showing 20 changed files with 490 additions and 124 deletions.
15 changes: 6 additions & 9 deletions src/parsimmon.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,6 @@ function alt() {
if (result.status) {
return result;
}
state = result.state;
}
return result;
});
Expand Down Expand Up @@ -458,7 +457,7 @@ _.times = function(min, max) {
for (var times = 0; times < min; times += 1) {
result = self._(input, i, state);
prevResult = mergeReplies(result, prevResult);
state = result.state;
state = prevResult.state;
if (result.status) {
i = result.index;
accum.push(result.value);
Expand All @@ -467,9 +466,9 @@ _.times = function(min, max) {
}
}
for (; times < max; times += 1) {
result = self._(input, i);
result = self._(input, i, state);
prevResult = mergeReplies(result, prevResult);
state = result.state;
state = prevResult.state;
if (result.status) {
i = result.index;
accum.push(result.value);
Expand Down Expand Up @@ -618,11 +617,9 @@ function regexp(re, group) {
var groupMatch = match[group];
return makeSuccess(i + fullMatch.length, groupMatch, state);
}
return makeFailure(
i,
'valid match group (0 to ' + match.length + ') in ' + expected,
state
);
var expected2 =
'valid match group (0 to ' + match.length + ') in ' + expected;
return makeFailure(i, expected2, state);
}
return makeFailure(i, expected, state);
});
Expand Down
18 changes: 18 additions & 0 deletions test/core/all.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

suite('all', function() {

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
test(10)
.then(Parsimmon.all)
.then(test(10))
.tryParse('memes', 10);
});

});
87 changes: 56 additions & 31 deletions test/core/alt.test.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,69 @@
'use strict';

test('Parsimmon.alt', function(){
var toNode = function(nodeType){
return function(value) {
return {type: nodeType, value: value};
suite('Parsimmon.alt', function() {

test('should work in general', function() {
var toNode = function(nodeType){
return function(value) {
return {type: nodeType, value: value};
};
};
};

var stringParser = Parsimmon.seq(
Parsimmon.string('"'),
Parsimmon.regexp(/[^"]*/),
Parsimmon.string('"')
).map(toNode('string'));
var stringParser = Parsimmon.seq(
Parsimmon.string('"'),
Parsimmon.regexp(/[^"]*/),
Parsimmon.string('"')
).map(toNode('string'));

var identifierParser =
Parsimmon.regexp(/[a-zA-Z]*/)
.map(toNode('identifier'));
var identifierParser =
Parsimmon.regexp(/[a-zA-Z]*/)
.map(toNode('identifier'));

var parser = Parsimmon.alt(stringParser, identifierParser);
var parser = Parsimmon.alt(stringParser, identifierParser);

assert.deepEqual(
parser.parse('"a string, to be sure"').value,
{
type: 'string',
value: ['"', 'a string, to be sure', '"']
}
);
assert.deepEqual(
parser.parse('"a string, to be sure"').value,
{
type: 'string',
value: ['"', 'a string, to be sure', '"']
}
);

assert.deepEqual(
parser.parse('anIdentifier').value,
{
type: 'identifier',
value: 'anIdentifier'
}
);
assert.deepEqual(
parser.parse('anIdentifier').value,
{
type: 'identifier',
value: 'anIdentifier'
}
);

assert.throws(function() {
Parsimmon.alt('not a parser');
});

assert.throws(function() {
Parsimmon.alt('not a parser');

assert.strictEqual(Parsimmon.alt().parse('').status, false);
});

test('should pass state through each parser', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var inc = Parsimmon(function(input, i, state) {
return Parsimmon.makeSuccess(i, null, state + 1);
});
var a = Parsimmon.string('a');
var b = Parsimmon.string('b');
var c = Parsimmon.string('c');
var parser = Parsimmon.alt(
test(0).then(inc).then(a).skip(test(1)),
test(0).then(inc).then(b).skip(test(1)),
test(0).then(inc).then(c).skip(test(1))
).then(test(1));
parser.tryParse('c', 0);
});

assert.strictEqual(Parsimmon.alt().parse('').status, false);
});
18 changes: 18 additions & 0 deletions test/core/any.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

suite('any', function() {

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
test(10)
.then(Parsimmon.any)
.then(test(10))
.tryParse('x', 10);
});

});
20 changes: 20 additions & 0 deletions test/core/chain.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,24 @@ suite('chain', function() {
assert.ok(!parser.parse('x').status);
});

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
function always10() {
return 10;
}
var inc = Parsimmon(function(input, i, state) {
return Parsimmon.makeSuccess(i, null, state + 1);
});
Parsimmon.any.chain(function() {
return test()
})
test(0).then(Parsimmon.any.map(always10)).skip(test(0)).tryParse('a', 0);
inc.then(Parsimmon.any.map(always10)).skip(test(1)).tryParse('b', 0);
});

});
16 changes: 16 additions & 0 deletions test/core/desc.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,20 @@ suite('desc', function() {
expected: ['the letter y']
});
});

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var inc = Parsimmon(function(input, i, state) {
return Parsimmon.makeSuccess(i, null, state + 1);
});
var parser = Parsimmon.any.desc('by any other name?');
test(0).then(parser).skip(test(0)).tryParse('a', 0);
inc.then(parser).skip(test(1)).tryParse('b', 0);
});

});
33 changes: 25 additions & 8 deletions test/core/eof.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
'use strict';

test('eof', function() {
var parser =
Parsimmon.optWhitespace
.skip(Parsimmon.eof)
.or(Parsimmon.all.result('default'));

assert.equal(parser.parse(' ').value, ' ');
assert.equal(parser.parse('x').value, 'default');
suite('eof', function() {

test('should work in general', function() {
var parser =
Parsimmon.optWhitespace
.skip(Parsimmon.eof)
.or(Parsimmon.all.result('default'));

assert.equal(parser.parse(' ').value, ' ');
assert.equal(parser.parse('x').value, 'default');
});

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
test(10)
.then(Parsimmon.eof)
.then(test(10))
.tryParse('', 10);
});

});
29 changes: 29 additions & 0 deletions test/core/fail.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,33 @@ suite('fail', function() {
expected: ['*']
});
});

test('.fail should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var result =
test(10)
.then(Parsimmon.fail('nice'))
._(0, 'a', 10);
assert.strictEqual(result.state, 10);
});

test('.succeed should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var result =
test(10)
.then(Parsimmon.succeed('anything at all'))
._(0, 'a', 10);
assert.strictEqual(result.state, 10);
});

});
47 changes: 32 additions & 15 deletions test/core/index.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
'use strict';

test('index', function() {
var parser = Parsimmon.regexp(/^[x\n]*/).then(Parsimmon.index);
assert.deepEqual(parser.parse('').value, {
offset: 0,
line: 1,
column: 1
});
assert.deepEqual(parser.parse('xx').value, {
offset: 2,
line: 1,
column: 3
suite('index', function() {

test('should work in general', function() {
var parser = Parsimmon.regexp(/^[x\n]*/).then(Parsimmon.index);
assert.deepEqual(parser.parse('').value, {
offset: 0,
line: 1,
column: 1
});
assert.deepEqual(parser.parse('xx').value, {
offset: 2,
line: 1,
column: 3
});
assert.deepEqual(parser.parse('xx\nxx').value, {
offset: 5,
line: 2,
column: 3
});
});
assert.deepEqual(parser.parse('xx\nxx').value, {
offset: 5,
line: 2,
column: 3

test('should pass state through', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
test(10)
.then(Parsimmon.index)
.then(test(10))
.tryParse('', 10);
});

});
19 changes: 19 additions & 0 deletions test/core/lookahead.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,23 @@ suite('Parsimmon.lookahead', function() {
assert.throws(function() { Parsimmon.lookahead(12); });
});

test('should pass state through unchanged', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var inc = Parsimmon(function(input, i, state) {
return Parsimmon.makeSuccess(i, null, state + 1);
});
var parser = Parsimmon.lookahead(Parsimmon.regexp(/a/));
test(0)
.then(inc)
.then(parser)
.skip(test(1))
.then(Parsimmon.string('a'))
.tryParse('a', 0);
});

});
14 changes: 14 additions & 0 deletions test/core/many.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,18 @@ suite('many', function() {
assert.equal(parser.parse('xxxxxy').value, 'y');
});

test('should pass state through each parser', function() {
function test(n) {
return Parsimmon(function(input, i, state) {
assert.strictEqual(state, n);
return Parsimmon.makeSuccess(i, undefined, state);
});
}
var inc = Parsimmon(function(input, i, state) {
return Parsimmon.makeSuccess(i, null, state + 1);
});
var parser = Parsimmon.any.then(inc).many().then(test(4));
parser.tryParse('abcd', 0);
});

});
Loading

0 comments on commit 32316cf

Please sign in to comment.