Socket
Socket
Sign inDemoInstall

parsimmon

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

parsimmon - npm Package Compare versions

Comparing version 0.0.6 to 0.1.0

test/browser.html

5

package.json
{
"name": "parsimmon",
"version": "0.0.6",
"version": "0.1.0",
"description": "A monadic LL(infinity) parser combinator library",

@@ -12,3 +12,4 @@ "keywords": ["parsing", "parse", "parser combinators"],

"devDependencies": {
"mocha": "*",
"mocha": "1.8.x",
"chai": "1.5.x",
"uglify-js": "2.x"

@@ -15,0 +16,0 @@ },

@@ -105,2 +105,3 @@ [![Build Status](https://secure.travis-ci.org/jayferd/parsimmon.png)](http://travis-ci.org/jayferd/parsimmon)

- `Parsimmon.eof` expects the end of the stream.
- `Parsimmon.index` is a parser that yields the current index of the parse.

@@ -135,3 +136,13 @@ ### Parser methods

expects `parser` at least `n` times. Yields an array of the results.
- `parser.mark()` yields an object with `start`, `value`, and `end` keys, where
`value` is the original value yielded by the parser, and `start` and `end` are
the indices in the stream that contain the parsed text.
### Fantasyland
[fantasyland]: https://github.com/fantasyland/fantasy-land "Fantasyland"
[fantasyland-logo]: https://github.com/fantasyland/fantasy-land/raw/master/logo.png
![][fantasyland-logo]
Parsimmon is also compatible with [fantasyland][]. It is a Semigroup, an Applicative Functor and a Monad.

@@ -12,3 +12,39 @@ var Parsimmon = {};

function parseError(stream, i, expected) {
function makeSuccess(index, value) {
return {
status: true,
index: index,
value: value,
furthest: -1,
expected: ''
};
}
function makeFailure(index, expected) {
return {
status: false,
index: -1,
value: null,
furthest: index,
expected: expected
};
}
function furthestBacktrackFor(result, last) {
if (!last) return result;
if (result.furthest >= last.furthest) return result;
return {
status: result.status,
index: result.index,
value: result.value,
furthest: last.furthest,
expected: last.expected
}
}
function parseError(stream, result) {
var expected = result.expected;
var i = result.furthest;
if (i === stream.length) {

@@ -29,23 +65,7 @@ var message = 'expected ' + expected + ', got the end of the string';

_.parse = function(stream) {
return this.skip(eof)._(stream, 0, success, parseError);
var result = this.skip(eof)._(stream, 0);
function success(stream, i, result) { return result; }
return result.status ? result.value : parseError(stream, result);
};
function furthestFailure(onFailure, myI, myExpected) {
return function(stream, yourI, yourExpected) {
if (myI > yourI) return onFailure(stream, myI, myExpected);
else return onFailure.apply(this, arguments);
};
}
function furthestFailureSuccess(onSuccess, myFurthestFailureI, myFurthestExpected) {
return function(stream, i, result, yourFurthestFailureI, yourFurthestExpected) {
if (myFurthestFailureI > yourFurthestFailureI) {
return onSuccess(stream, i, result, myFurthestFailureI, myFurthestExpected);
}
else return onSuccess.apply(this, arguments);
};
}
// -*- primitive combinators -*- //

@@ -55,10 +75,6 @@ _.or = function(alternative) {

return Parser(function(stream, i, onSuccess, onFailure) {
return self._(stream, i, onSuccess, failure);
return Parser(function(stream, i) {
var result = self._(stream, i);
function failure(stream, newI, expected) {
var altSuccess = furthestFailureSuccess(onSuccess, newI, expected);
var altFailure = furthestFailure(onFailure, newI, expected);
return alternative._(stream, i, altSuccess, altFailure);
}
return result.status ? result : furthestBacktrackFor(alternative._(stream, i), result);
});

@@ -70,11 +86,12 @@ };

return Parser(function(stream, i, onSuccess, onFailure) {
return self._(stream, i, success, onFailure);
return Parser(function(stream, i) {
var result = self._(stream, i);
function success(stream, newI, result, furthestFailureI, furthestExpected) {
var nextParser = (next instanceof Parser ? next : next(result));
var nextSuccess = furthestFailureSuccess(onSuccess, furthestFailureI, furthestExpected);
var nextFailure = furthestFailure(onFailure, furthestFailureI, furthestExpected);
return nextParser._(stream, newI, nextSuccess, nextFailure);
if (result.status) {
var nextParser = (next instanceof Parser ? next : next(result.value));
return furthestBacktrackFor(nextParser._(stream, result.index), result);
}
else {
return result;
}
});

@@ -100,22 +117,18 @@ };

return Parser(function(stream, i, onSuccess, onFailure) {
var xs = [];
while (self._(stream, i, success, failure));
var furthestFailureI, furthestExpected;
return onSuccess(stream, i, xs, furthestFailureI, furthestExpected);
return Parser(function(stream, i) {
var accum = [];
var result;
var prevResult;
function success(stream, newI, x, successFurthestFailureI, successFurthestExpected) {
i = newI;
xs.push(x);
furthestFailureI = successFurthestFailureI;
furthestExpected = successFurthestExpected;
return true;
}
for (;;) {
result = self._(stream, i);
prevResult = furthestBacktrackFor(result, prevResult);
function failure(stream, newI, expected) {
if (!(furthestFailureI > newI)) {
furthestFailureI = newI;
furthestExpected = expected;
if (result.status) {
i = result.index;
accum.push(result.value);
}
return false;
else {
return furthestBacktrackFor(makeSuccess(i, accum), prevResult);
}
}

@@ -149,33 +162,33 @@ });

return Parser(function(stream, i, onSuccess, onFailure) {
var xs = [];
var result = true;
var furthestFailureI, furthestExpected;
return Parser(function(stream, i) {
var accum = [];
var start = i;
var result;
var prevResult;
for (var times = 0; times < min; times += 1) {
result = self._(stream, i, success, failure);
if (!result) return onFailure(stream, furthestFailureI, furthestExpected);
result = self._(stream, i);
prevResult = furthestBacktrackFor(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
}
else {
return prevResult;
}
}
for (; times < max && result; times += 1) {
result = self._(stream, i, success, failure);
result = self._(stream, i);
prevResult = furthestBacktrackFor(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
}
else {
break;
}
}
return onSuccess(stream, i, xs, furthestFailureI, furthestExpected);
function success(stream, newI, x, successFurthestFailureI, successFurthestExpected) {
i = newI;
xs.push(x);
furthestFailureI = successFurthestFailureI;
furthestExpected = successFurthestExpected;
return true;
}
function failure(stream, newI, expected) {
if (!(furthestFailureI > newI)) {
furthestFailureI = newI;
furthestExpected = expected;
}
return false;
}
return furthestBacktrackFor(makeSuccess(i, accum), prevResult);
});

@@ -204,2 +217,14 @@ };

// TODO: this would be better implemented with `seq`
_.mark = function() {
var self = this;
return index.then(function(start) {
return self.then(function(value) {
return index.map(function(end) {
return { start: start, value: value, end: end };
});
});
});
};
// -*- primitive parsers -*- //

@@ -210,10 +235,10 @@ var string = Parsimmon.string = function(str) {

return Parser(function(stream, i, onSuccess, onFailure) {
return Parser(function(stream, i) {
var head = stream.slice(i, i+len);
if (head === str) {
return onSuccess(stream, i+len, head, -1);
return makeSuccess(i+len, head);
}
else {
return onFailure(stream, i, expected);
return makeFailure(i, expected);
}

@@ -228,3 +253,3 @@ });

return Parser(function(stream, i, onSuccess, onFailure) {
return Parser(function(stream, i) {
var match = re.exec(stream.slice(i));

@@ -234,6 +259,6 @@

var result = match[0];
return onSuccess(stream, i+result.length, result, -1);
return makeSuccess(i+result.length, result);
}
else {
return onFailure(stream, i, expected);
return makeFailure(i, re);
}

@@ -243,5 +268,5 @@ });

var succeed = Parsimmon.succeed = function(result) {
return Parser(function(stream, i, onSuccess) {
return onSuccess(stream, i, result);
var succeed = Parsimmon.succeed = function(value) {
return Parser(function(stream, i) {
return makeSuccess(i, value);
});

@@ -251,5 +276,3 @@ };

var fail = Parsimmon.fail = function(expected) {
return Parser(function(stream, i, _, onFailure) {
return onFailure(stream, i, expected);
});
return Parser(function(stream, i) { return makeFailure(i, expected); });
};

@@ -264,17 +287,41 @@

var any = Parsimmon.any = Parser(function(stream, i, onSuccess, onFailure) {
if (i >= stream.length) return onFailure(stream, i, 'any character');
var any = Parsimmon.any = Parser(function(stream, i) {
if (i >= stream.length) return makeFailure(i, 'any character');
return onSuccess(stream, i+1, stream.charAt(i), -1);
return makeSuccess(i+1, stream.charAt(i));
});
var all = Parsimmon.all = Parser(function(stream, i, onSuccess, onFailure) {
return onSuccess(stream, stream.length, stream.slice(i), -1);
var all = Parsimmon.all = Parser(function(stream, i) {
return makeSuccess(stream.length, stream.slice(i));
});
var eof = Parsimmon.eof = Parser(function(stream, i, onSuccess, onFailure) {
if (i < stream.length) return onFailure(stream, i, 'EOF');
var eof = Parsimmon.eof = Parser(function(stream, i) {
if (i < stream.length) return makeFailure(i, 'EOF');
return onSuccess(stream, i, '', -1);
return makeSuccess(i, null);
});
var index = Parsimmon.index = Parser(function(stream, i) {
return makeSuccess(i, i);
});
//- fantasyland compat
//- Semigroup
_.concat = _.then;
//- Applicative
_.of = Parser.of = Parsimmon.of = succeed
// TODO: this could be better implemented with `seq`
_.ap = function(other) {
return this.then(function(fn) {
return other.then(function(val) {
return fn(val);
});
});
};
//- Monad
_.chain = _.then;
});

57

test/parsimmon.test.js

@@ -1,10 +0,1 @@

var assert = require('assert')
, Parsimmon = require('./../index')
, mocha = require('mocha')
;
function partialEquals(x) {
return function(y) { return x === y; }
}
suite('parser', function() {

@@ -20,2 +11,3 @@ var string = Parsimmon.string;

var all = Parsimmon.all;
var index = Parsimmon.index;

@@ -26,3 +18,3 @@ test('Parsimmon.string', function() {

assert.throws(function() { parser.parse('y') },
partialEquals("Parse Error: expected 'x' at character 0, got 'y'\n parsing: 'y'"));
"Parse Error: expected 'x' at character 0, got 'y'\n parsing: 'y'");
});

@@ -36,3 +28,3 @@

assert.throws(function() { parser.parse('x'); },
partialEquals("Parse Error: expected /^[0-9]/ at character 0, got 'x'\n parsing: 'x'"));
"Parse Error: expected /^[0-9]/ at character 0, got 'x'\n parsing: 'x'");
assert.throws(function() { regex(/./) }, 'must be anchored');

@@ -46,5 +38,5 @@ });

assert.throws(function() { parser.parse('y'); },
partialEquals("Parse Error: expected 'x' at character 0, got 'y'\n parsing: 'y'"));
"Parse Error: expected 'x' at character 0, got 'y'\n parsing: 'y'");
assert.throws(function() { parser.parse('xz'); },
partialEquals("Parse Error: expected 'y' at character 1, got '...z'\n parsing: 'xz'"));
"Parse Error: expected 'y' at character 1, got '...z'\n parsing: 'xz'");
});

@@ -215,3 +207,3 @@

assert.throws(function() { parser.parse('y'); },
partialEquals("Parse Error: expected a character besides y, got the end of the string\n parsing: 'y'"));
"Parse Error: expected a character besides y, got the end of the string\n parsing: 'y'");
assert.equal(parser.parse('x'), 'x');

@@ -236,3 +228,3 @@ });

assert.throws(function() { parser.parse('x*y'); },
partialEquals("Parse Error: expected + at character 2, got '...y'\n parsing: 'x*y'"));
"Parse Error: expected + at character 2, got '...y'\n parsing: 'x*y'");

@@ -242,3 +234,3 @@ allowedOperator = '*';

assert.throws(function() { parser.parse('x+y'); },
partialEquals("Parse Error: expected * at character 2, got '...y'\n parsing: 'x+y'"));
"Parse Error: expected * at character 2, got '...y'\n parsing: 'x+y'");
});

@@ -254,2 +246,16 @@ });

test('index', function() {
var parser = regex(/^x*/).then(index);
assert.equal(parser.parse(''), 0);
assert.equal(parser.parse('xx'), 2);
assert.equal(parser.parse('xxxx'), 4);
});
test('mark', function() {
var ys = regex(/^y*/).mark()
var parser = optWhitespace.then(ys).skip(optWhitespace);
assert.deepEqual(parser.parse(''), { start: 0, value: '', end: 0 });
assert.deepEqual(parser.parse(' yy '), { start: 1, value: 'yy', end: 3 });
});
suite('smart error messages', function() {

@@ -264,3 +270,3 @@ // this is mainly about .or(), .many(), and .times(), but not about

assert.throws(function() { parser.parse('abc'); },
partialEquals("Parse Error: expected 'def', got the end of the string\n parsing: 'abc'"));
"Parse Error: expected 'def', got the end of the string\n parsing: 'abc'");
});

@@ -272,3 +278,3 @@

assert.throws(function() { parser.parse('abc'); },
partialEquals("Parse Error: expected 'd', got the end of the string\n parsing: 'abc'"));
"Parse Error: expected 'd', got the end of the string\n parsing: 'abc'");
});

@@ -281,3 +287,3 @@

assert.throws(function() { parser.parse('abcdef'); },
partialEquals("Parse Error: expected 'g', got the end of the string\n parsing: 'abcdef'"));
"Parse Error: expected 'g', got the end of the string\n parsing: 'abcdef'");
});

@@ -292,8 +298,9 @@ });

assert.deepEqual(list.parse('(a b) (c ((() d)))'), [['a', 'b'], ['c', [[[], 'd']]]]);
// assert.deepEqual(list.parse('(a b) (c ((() d)))'), [['a', 'b'], ['c', [[[], 'd']]]]);
assert.throws(function() { list.parse('(a b ()) c)'); },
partialEquals("Parse Error: expected EOF at character 10, got '...)'\n parsing: '(a b ()) c)'"));
"Parse Error: expected EOF at character 10, got '...)'\n parsing: '(a b ()) c)'");
assert.throws(function() { list.parse('(a (b)) (() c'); },
partialEquals("Parse Error: expected ')', got the end of the string\n parsing: '(a (b)) (() c'"));
"Parse Error: expected ')', got the end of the string\n parsing: '(a (b)) (() c'");
});

@@ -307,3 +314,3 @@

assert.throws(function() { parser.parse('aaabcde'); },
partialEquals("Parse Error: expected 'def' at character 5, got '...de'\n parsing: 'aaabcde'"));
"Parse Error: expected 'def' at character 5, got '...de'\n parsing: 'aaabcde'");
});

@@ -317,6 +324,6 @@ });

assert.throws(function() { parser.parse('aabcde'); },
partialEquals("Parse Error: expected 'def' at character 4, got '...de'\n parsing: 'aabcde'"));
"Parse Error: expected 'def' at character 4, got '...de'\n parsing: 'aabcde'");
assert.throws(function() { parser.parse('aaaaabcde'); },
partialEquals("Parse Error: expected 'def' at character 7, got '...de'\n parsing: 'aaaaabcde'"));
"Parse Error: expected 'def' at character 7, got '...de'\n parsing: 'aaaaabcde'");
});

@@ -323,0 +330,0 @@ });

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc