Socket
Socket
Sign inDemoInstall

parsimmon

Package Overview
Dependencies
Maintainers
3
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.7.0 to 0.7.1

CHANGELOG.md

88

build/parsimmon.browser.js

@@ -57,5 +57,18 @@ // pass

// For ensuring we have the right argument types
function assertParser(p) {
if (!(p instanceof Parser)) throw new Error('not a parser: '+p);
}
function assertNumber(x) {
if (typeof x !== 'number') throw new Error('not a number: '+x);
}
function assertRegexp(x) {
if (!(x instanceof RegExp)) throw new Error('not a regex: '+x);
}
function assertFunction(x) {
if (typeof x !== 'function') throw new Error('not a function: '+x);
}
function assertString(x) {
if (typeof x !== 'string') throw new Error('not a string: '+x)
}

@@ -69,3 +82,4 @@ function formatExpected(expected) {

function formatGot(stream, error) {
var i = error.index;
var index = error.index;
var i = index.offset;

@@ -78,3 +92,4 @@ if (i === stream.length) return ', got the end of the stream'

return ' at character ' + i + ', got ' + prefix + stream.slice(i, i+12) + suffix
return ' at line ' + index.line + ' column ' + index.column
+ ', got ' + prefix + stream.slice(i, i+12) + suffix
}

@@ -87,2 +102,5 @@

_.parse = function(stream) {
if (typeof stream !== 'string') {
throw new Error('.parse must be called with a string as its argument');
}
var result = this.skip(eof)._(stream, 0);

@@ -95,3 +113,3 @@

status: false,
index: result.furthest,
index: makeLineColumnIndex(stream, result.furthest),
expected: result.expected

@@ -106,2 +124,6 @@ };

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -143,2 +165,6 @@ var result;

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -154,2 +180,20 @@ var result;

var sepBy = Parsimmon.sepBy = function(parser, separator) {
// Argument asserted by sepBy1
return sepBy1(parser, separator).or(Parsimmon.of([]));
};
var sepBy1 = Parsimmon.sepBy1 = function(parser, separator) {
assertParser(parser);
assertParser(separator);
var pairs = separator.then(parser).many();
return parser.chain(function(r) {
return pairs.map(function(rs) {
return [r].concat(rs);
})
})
};
// -*- primitive combinators -*- //

@@ -229,2 +273,5 @@ _.or = function(alternative) {

assertNumber(min);
assertNumber(max);
return Parser(function(stream, i) {

@@ -271,2 +318,5 @@ var accum = [];

_.map = function(fn) {
assertFunction(fn);
var self = this;

@@ -304,2 +354,4 @@ return Parser(function(stream, i) {

assertString(str);
return Parser(function(stream, i) {

@@ -318,2 +370,6 @@ var head = stream.slice(i, i+len);

var regex = Parsimmon.regex = function(re, group) {
assertRegexp(re);
if (group) assertNumber(group);
var anchored = RegExp('^(?:'+re.source+')', (''+re).slice((''+re).lastIndexOf('/')+1));

@@ -370,2 +426,4 @@ var expected = '' + re;

var test = Parsimmon.test = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -391,2 +449,4 @@ var char = stream.charAt(i);

var takeWhile = Parsimmon.takeWhile = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -415,6 +475,22 @@ var j = i;

var index = Parsimmon.index = Parser(function(stream, i) {
return makeSuccess(i, i);
});
var makeLineColumnIndex = function(stream, i) {
var lines = stream.slice(0, i).split("\n");
// Note that unlike the character offset, the line and column offsets are
// 1-based.
var lineWeAreUpTo = lines.length;
var columnWeAreUpTo = lines[lines.length - 1].length + 1;
return {
offset: i,
line: lineWeAreUpTo,
column: columnWeAreUpTo
};
};
var index
= Parsimmon.index
= Parser(function(stream, i) {
return makeSuccess(i, makeLineColumnIndex(stream, i));
});
//- fantasyland compat

@@ -421,0 +497,0 @@

2

build/parsimmon.browser.min.js

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

var Parsimmon={};Parsimmon.Parser=function(){"use strict";function r(n){if(!(this instanceof r))return new r(n);this._=n}var n=r.prototype;function t(r,n){return{status:true,index:r,value:n,furthest:-1,expected:[]}}function e(r,n){return{status:false,index:-1,value:null,furthest:r,expected:[n]}}function u(r,n){if(!n)return r;if(r.furthest>n.furthest)return r;var t=r.furthest===n.furthest?r.expected.concat(n.expected):n.expected;return{status:r.status,index:r.index,value:r.value,furthest:n.furthest,expected:t}}function a(n){if(!(n instanceof r))throw new Error("not a parser: "+n)}function i(r){if(r.length===1)return r[0];return"one of "+r.join(", ")}function s(r,n){var t=n.index;if(t===r.length)return", got the end of the stream";var e=t>0?"'...":"'";var u=r.length-t>12?"...'":"'";return" at character "+t+", got "+e+r.slice(t,t+12)+u}var o=Parsimmon.formatError=function(r,n){return"expected "+i(n.expected)+s(r,n)};n.parse=function(r){var n=this.skip(E)._(r,0);return n.status?{status:true,value:n.value}:{status:false,index:n.furthest,expected:n.expected}};var f=Parsimmon.seq=function(){var n=[].slice.call(arguments);var e=n.length;return r(function(r,a){var i;var s=new Array(e);for(var o=0;o<e;o+=1){i=u(n[o]._(r,a),i);if(!i.status)return i;s[o]=i.value;a=i.index}return u(t(a,s),i)})};var c=Parsimmon.seqMap=function(){var r=[].slice.call(arguments);var n=r.pop();return f.apply(null,r).map(function(r){return n.apply(null,r)})};var v=Parsimmon.custom=function(n){return r(n(t,e))};var l=Parsimmon.alt=function(){var n=[].slice.call(arguments);var t=n.length;if(t===0)return d("zero alternates");return r(function(r,t){var e;for(var a=0;a<n.length;a+=1){e=u(n[a]._(r,t),e);if(e.status)return e}return e})};n.or=function(r){return l(this,r)};n.then=function(r){if(typeof r==="function"){throw new Error("chaining features of .then are no longer supported, use .chain instead")}a(r);return f(this,r).map(function(r){return r[1]})};n.many=function(){var n=this;return r(function(r,e){var a=[];var i;var s;for(;;){i=u(n._(r,e),i);if(i.status){e=i.index;a.push(i.value)}else{return u(t(e,a),i)}}})};n.times=function(n,e){if(arguments.length<2)e=n;var a=this;return r(function(r,i){var s=[];var o=i;var f;var c;for(var v=0;v<n;v+=1){f=a._(r,i);c=u(f,c);if(f.status){i=f.index;s.push(f.value)}else return c}for(;v<e;v+=1){f=a._(r,i);c=u(f,c);if(f.status){i=f.index;s.push(f.value)}else break}return u(t(i,s),c)})};n.result=function(r){return this.map(function(n){return r})};n.atMost=function(r){return this.times(0,r)};n.atLeast=function(r){var n=this;return c(this.times(r),this.many(),function(r,n){return r.concat(n)})};n.map=function(n){var e=this;return r(function(r,a){var i=e._(r,a);if(!i.status)return i;return u(t(i.index,n(i.value)),i)})};n.skip=function(r){return f(this,r).map(function(r){return r[0]})};n.mark=function(){return c(b,this,b,function(r,n,t){return{start:r,value:n,end:t}})};n.desc=function(n){var t=this;return r(function(r,e){var u=t._(r,e);if(!u.status)u.expected=[n];return u})};var m=Parsimmon.string=function(n){var u=n.length;var a="'"+n+"'";return r(function(r,i){var s=r.slice(i,i+u);if(s===n){return t(i+u,s)}else{return e(i,a)}})};var h=Parsimmon.regex=function(n,u){var a=RegExp("^(?:"+n.source+")",(""+n).slice((""+n).lastIndexOf("/")+1));var i=""+n;if(u==null)u=0;return r(function(r,n){var s=a.exec(r.slice(n));if(s){var o=s[0];var f=s[u];if(f!=null)return t(n+o.length,f)}return e(n,i)})};var p=Parsimmon.succeed=function(n){return r(function(r,e){return t(e,n)})};var d=Parsimmon.fail=function(n){return r(function(r,t){return e(t,n)})};var g=Parsimmon.letter=h(/[a-z]/i).desc("a letter");var x=Parsimmon.letters=h(/[a-z]*/i);var P=Parsimmon.digit=h(/[0-9]/).desc("a digit");var _=Parsimmon.digits=h(/[0-9]*/);var y=Parsimmon.whitespace=h(/\s+/).desc("whitespace");var w=Parsimmon.optWhitespace=h(/\s*/);var O=Parsimmon.any=r(function(r,n){if(n>=r.length)return e(n,"any character");return t(n+1,r.charAt(n))});var k=Parsimmon.all=r(function(r,n){return t(r.length,r.slice(n))});var E=Parsimmon.eof=r(function(r,n){if(n<r.length)return e(n,"EOF");return t(n,null)});var z=Parsimmon.test=function(n){return r(function(r,u){var a=r.charAt(u);if(u<r.length&&n(a)){return t(u+1,a)}else{return e(u,"a character matching "+n)}})};var A=Parsimmon.oneOf=function(r){return z(function(n){return r.indexOf(n)>=0})};var q=Parsimmon.noneOf=function(r){return z(function(n){return r.indexOf(n)<0})};var M=Parsimmon.takeWhile=function(n){return r(function(r,e){var u=e;while(u<r.length&&n(r.charAt(u)))u+=1;return t(u,r.slice(e,u))})};var W=Parsimmon.lazy=function(n,t){if(arguments.length<2){t=n;n=undefined}var e=r(function(r,n){e._=t()._;return e._(r,n)});if(n)e=e.desc(n);return e};var b=Parsimmon.index=r(function(r,n){return t(n,n)});n.concat=n.or;n.empty=d("empty");n.of=r.of=Parsimmon.of=p;n.ap=function(r){return c(this,r,function(r,n){return r(n)})};n.chain=function(n){var t=this;return r(function(r,e){var a=t._(r,e);if(!a.status)return a;var i=n(a.value);return u(i._(r,a.index),a)})};return r}();
var Parsimmon={};Parsimmon.Parser=function(){"use strict";function r(n){if(!(this instanceof r))return new r(n);this._=n}var n=r.prototype;function t(r,n){return{status:true,index:r,value:n,furthest:-1,expected:[]}}function e(r,n){return{status:false,index:-1,value:null,furthest:r,expected:[n]}}function i(r,n){if(!n)return r;if(r.furthest>n.furthest)return r;var t=r.furthest===n.furthest?r.expected.concat(n.expected):n.expected;return{status:r.status,index:r.index,value:r.value,furthest:n.furthest,expected:t}}function u(n){if(!(n instanceof r))throw new Error("not a parser: "+n)}function a(r){if(typeof r!=="number")throw new Error("not a number: "+r)}function o(r){if(!(r instanceof RegExp))throw new Error("not a regex: "+r)}function s(r){if(typeof r!=="function")throw new Error("not a function: "+r)}function f(r){if(typeof r!=="string")throw new Error("not a string: "+r)}function c(r){if(r.length===1)return r[0];return"one of "+r.join(", ")}function v(r,n){var t=n.index;var e=t.offset;if(e===r.length)return", got the end of the stream";var i=e>0?"'...":"'";var u=r.length-e>12?"...'":"'";return" at line "+t.line+" column "+t.column+", got "+i+r.slice(e,e+12)+u}var l=Parsimmon.formatError=function(r,n){return"expected "+c(n.expected)+v(r,n)};n.parse=function(r){if(typeof r!=="string"){throw new Error(".parse must be called with a string as its argument")}var n=this.skip(M)._(r,0);return n.status?{status:true,value:n.value}:{status:false,index:L(r,n.furthest),expected:n.expected}};var m=Parsimmon.seq=function(){var n=[].slice.call(arguments);var e=n.length;for(var a=0;a<e;a+=1){u(n[a])}return r(function(r,u){var a;var o=new Array(e);for(var s=0;s<e;s+=1){a=i(n[s]._(r,u),a);if(!a.status)return a;o[s]=a.value;u=a.index}return i(t(u,o),a)})};var h=Parsimmon.seqMap=function(){var r=[].slice.call(arguments);var n=r.pop();return m.apply(null,r).map(function(r){return n.apply(null,r)})};var p=Parsimmon.custom=function(n){return r(n(t,e))};var d=Parsimmon.alt=function(){var n=[].slice.call(arguments);var t=n.length;if(t===0)return _("zero alternates");for(var e=0;e<t;e+=1){u(n[e])}return r(function(r,t){var e;for(var u=0;u<n.length;u+=1){e=i(n[u]._(r,t),e);if(e.status)return e}return e})};var g=Parsimmon.sepBy=function(r,n){return x(r,n).or(Parsimmon.of([]))};var x=Parsimmon.sepBy1=function(r,n){u(r);u(n);var t=n.then(r).many();return r.chain(function(r){return t.map(function(n){return[r].concat(n)})})};n.or=function(r){return d(this,r)};n.then=function(r){if(typeof r==="function"){throw new Error("chaining features of .then are no longer supported, use .chain instead")}u(r);return m(this,r).map(function(r){return r[1]})};n.many=function(){var n=this;return r(function(r,e){var u=[];var a;var o;for(;;){a=i(n._(r,e),a);if(a.status){e=a.index;u.push(a.value)}else{return i(t(e,u),a)}}})};n.times=function(n,e){if(arguments.length<2)e=n;var u=this;a(n);a(e);return r(function(r,a){var o=[];var s=a;var f;var c;for(var v=0;v<n;v+=1){f=u._(r,a);c=i(f,c);if(f.status){a=f.index;o.push(f.value)}else return c}for(;v<e;v+=1){f=u._(r,a);c=i(f,c);if(f.status){a=f.index;o.push(f.value)}else break}return i(t(a,o),c)})};n.result=function(r){return this.map(function(n){return r})};n.atMost=function(r){return this.times(0,r)};n.atLeast=function(r){var n=this;return h(this.times(r),this.many(),function(r,n){return r.concat(n)})};n.map=function(n){s(n);var e=this;return r(function(r,u){var a=e._(r,u);if(!a.status)return a;return i(t(a.index,n(a.value)),a)})};n.skip=function(r){return m(this,r).map(function(r){return r[0]})};n.mark=function(){return h(C,this,C,function(r,n,t){return{start:r,value:n,end:t}})};n.desc=function(n){var t=this;return r(function(r,e){var i=t._(r,e);if(!i.status)i.expected=[n];return i})};var P=Parsimmon.string=function(n){var i=n.length;var u="'"+n+"'";f(n);return r(function(r,a){var o=r.slice(a,a+i);if(o===n){return t(a+i,o)}else{return e(a,u)}})};var w=Parsimmon.regex=function(n,i){o(n);if(i)a(i);var u=RegExp("^(?:"+n.source+")",(""+n).slice((""+n).lastIndexOf("/")+1));var s=""+n;if(i==null)i=0;return r(function(r,n){var a=u.exec(r.slice(n));if(a){var o=a[0];var f=a[i];if(f!=null)return t(n+o.length,f)}return e(n,s)})};var y=Parsimmon.succeed=function(n){return r(function(r,e){return t(e,n)})};var _=Parsimmon.fail=function(n){return r(function(r,t){return e(t,n)})};var E=Parsimmon.letter=w(/[a-z]/i).desc("a letter");var O=Parsimmon.letters=w(/[a-z]*/i);var k=Parsimmon.digit=w(/[0-9]/).desc("a digit");var b=Parsimmon.digits=w(/[0-9]*/);var z=Parsimmon.whitespace=w(/\s+/).desc("whitespace");var A=Parsimmon.optWhitespace=w(/\s*/);var q=Parsimmon.any=r(function(r,n){if(n>=r.length)return e(n,"any character");return t(n+1,r.charAt(n))});var B=Parsimmon.all=r(function(r,n){return t(r.length,r.slice(n))});var M=Parsimmon.eof=r(function(r,n){if(n<r.length)return e(n,"EOF");return t(n,null)});var R=Parsimmon.test=function(n){s(n);return r(function(r,i){var u=r.charAt(i);if(i<r.length&&n(u)){return t(i+1,u)}else{return e(i,"a character matching "+n)}})};var W=Parsimmon.oneOf=function(r){return R(function(n){return r.indexOf(n)>=0})};var j=Parsimmon.noneOf=function(r){return R(function(n){return r.indexOf(n)<0})};var F=Parsimmon.takeWhile=function(n){s(n);return r(function(r,e){var i=e;while(i<r.length&&n(r.charAt(i)))i+=1;return t(i,r.slice(e,i))})};var I=Parsimmon.lazy=function(n,t){if(arguments.length<2){t=n;n=undefined}var e=r(function(r,n){e._=t()._;return e._(r,n)});if(n)e=e.desc(n);return e};var L=function(r,n){var t=r.slice(0,n).split("\n");var e=t.length;var i=t[t.length-1].length+1;return{offset:n,line:e,column:i}};var C=Parsimmon.index=r(function(r,n){return t(n,L(r,n))});n.concat=n.or;n.empty=_("empty");n.of=r.of=Parsimmon.of=y;n.ap=function(r){return h(this,r,function(r,n){return r(n)})};n.chain=function(n){var t=this;return r(function(r,e){var u=t._(r,e);if(!u.status)return u;var a=n(u.value);return i(a._(r,u.index),u)})};return r}();

@@ -57,5 +57,18 @@ // pass

// For ensuring we have the right argument types
function assertParser(p) {
if (!(p instanceof Parser)) throw new Error('not a parser: '+p);
}
function assertNumber(x) {
if (typeof x !== 'number') throw new Error('not a number: '+x);
}
function assertRegexp(x) {
if (!(x instanceof RegExp)) throw new Error('not a regex: '+x);
}
function assertFunction(x) {
if (typeof x !== 'function') throw new Error('not a function: '+x);
}
function assertString(x) {
if (typeof x !== 'string') throw new Error('not a string: '+x)
}

@@ -69,3 +82,4 @@ function formatExpected(expected) {

function formatGot(stream, error) {
var i = error.index;
var index = error.index;
var i = index.offset;

@@ -78,3 +92,4 @@ if (i === stream.length) return ', got the end of the stream'

return ' at character ' + i + ', got ' + prefix + stream.slice(i, i+12) + suffix
return ' at line ' + index.line + ' column ' + index.column
+ ', got ' + prefix + stream.slice(i, i+12) + suffix
}

@@ -87,2 +102,5 @@

_.parse = function(stream) {
if (typeof stream !== 'string') {
throw new Error('.parse must be called with a string as its argument');
}
var result = this.skip(eof)._(stream, 0);

@@ -95,3 +113,3 @@

status: false,
index: result.furthest,
index: makeLineColumnIndex(stream, result.furthest),
expected: result.expected

@@ -106,2 +124,6 @@ };

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -143,2 +165,6 @@ var result;

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -154,2 +180,20 @@ var result;

var sepBy = Parsimmon.sepBy = function(parser, separator) {
// Argument asserted by sepBy1
return sepBy1(parser, separator).or(Parsimmon.of([]));
};
var sepBy1 = Parsimmon.sepBy1 = function(parser, separator) {
assertParser(parser);
assertParser(separator);
var pairs = separator.then(parser).many();
return parser.chain(function(r) {
return pairs.map(function(rs) {
return [r].concat(rs);
})
})
};
// -*- primitive combinators -*- //

@@ -229,2 +273,5 @@ _.or = function(alternative) {

assertNumber(min);
assertNumber(max);
return Parser(function(stream, i) {

@@ -271,2 +318,5 @@ var accum = [];

_.map = function(fn) {
assertFunction(fn);
var self = this;

@@ -304,2 +354,4 @@ return Parser(function(stream, i) {

assertString(str);
return Parser(function(stream, i) {

@@ -318,2 +370,6 @@ var head = stream.slice(i, i+len);

var regex = Parsimmon.regex = function(re, group) {
assertRegexp(re);
if (group) assertNumber(group);
var anchored = RegExp('^(?:'+re.source+')', (''+re).slice((''+re).lastIndexOf('/')+1));

@@ -370,2 +426,4 @@ var expected = '' + re;

var test = Parsimmon.test = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -391,2 +449,4 @@ var char = stream.charAt(i);

var takeWhile = Parsimmon.takeWhile = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -415,6 +475,22 @@ var j = i;

var index = Parsimmon.index = Parser(function(stream, i) {
return makeSuccess(i, i);
});
var makeLineColumnIndex = function(stream, i) {
var lines = stream.slice(0, i).split("\n");
// Note that unlike the character offset, the line and column offsets are
// 1-based.
var lineWeAreUpTo = lines.length;
var columnWeAreUpTo = lines[lines.length - 1].length + 1;
return {
offset: i,
line: lineWeAreUpTo,
column: columnWeAreUpTo
};
};
var index
= Parsimmon.index
= Parser(function(stream, i) {
return makeSuccess(i, makeLineColumnIndex(stream, i));
});
//- fantasyland compat

@@ -421,0 +497,0 @@

{
"name": "parsimmon",
"version": "0.7.0",
"version": "0.7.1",
"description": "A monadic LL(infinity) parser combinator library",
"keywords": ["parsing", "parse", "parser combinators"],
"author": "Jeanine Adkisson <jneen at jneen dot net>",
"contributors": [
"Brian Mock <brian@mockbrian.com>"
],
"repository": "git://github.com/jneen/parsimmon",

@@ -21,5 +24,4 @@

},
"dependencies": {
"pjs": "5.x"
},
"license": "MIT",
"dependencies": {},
"scripts": {

@@ -26,0 +28,0 @@ "test": "make test"

@@ -7,9 +7,13 @@ [![Build Status](https://secure.travis-ci.org/jneen/parsimmon.png)](http://travis-ci.org/jneen/parsimmon)

(by @jneen and @laughinghan)
**Authors:** [@jneen](https://github.com/jneen) and [@laughinghan](https://github.com/laughinghan)
**Maintainer:** [@wavebeem](https://github.com/wavebeem)
Parsimmon is a small library for writing big parsers made up of lots of little parsers. The API is inspired by parsec and Promises/A.
Parsimmon supports IE7 and newer browsers, along with Node.js. It can be used as a standard Node module through npm, or through `build/parsimmon.browser.js` directly in the browser through a script tag, where it exports a global variable called `Parsimmon`.
## Quick Example
``` js
```javascript
var regex = Parsimmon.regex;

@@ -49,3 +53,3 @@ var string = Parsimmon.string;

``` js
```javascript
string('foo').map(function(x) { return x + 'bar'; })

@@ -56,3 +60,3 @@ ```

``` js
```javascript
digits.map(function(x) { return parseInt(x) * 2; })

@@ -64,10 +68,9 @@ ```

Calling `.parse(str)` on a parser parses the string, and returns an
object with a `status` flag, indicating whether the parse succeeded.
If it succeeded, the `value` attribute will contain the yielded value.
Otherwise, the `index` and `expected` attributes will contain the
index of the parse error, and a message indicating what was expected.
Calling `.parse(str)` on a parser parses the string, and returns an object with
a `status` flag, indicating whether the parse succeeded. If it succeeded, the
`value` attribute will contain the yielded value. Otherwise, the `index` and
`expected` attributes will contain the index of the parse error (with `offset`,
`line` and `column` properties), and a message indicating what was expected.
The error object can be passed along with the original source to
`Parsimmon.formatError(source, error)` to obtain a human-readable
error string.
`Parsimmon.formatError(source, error)` to obtain a human-readable error string.

@@ -79,2 +82,7 @@ ## Full API

`"my-string"`, and will yield the same.
- `Parsimmon.oneOf("abc")` is a parser that expects to find
one of the characters `"a"`, `"b"`, or `"c"`, and will yield the same.
- `Parsimmon.noneOf("abc")` is a parser that expects to find
any character except one of the characters `"a"`, `"b"`, or `"c"`,
and will yield the same.
- `Parsimmon.regex(/myregex/, group=0)` is a parser that expects the stream

@@ -87,7 +95,16 @@ to match the given regex, and yields the given match group, or the

that it expects to find in order, yielding an array of the results.
- `Parsimmon.seqMap(parser1, parser2, ..., function(result1, result2, ...) { return anotherResult; })`:
matches all parsers sequentially, passing their results to the callback
at the end, returning its value. Works like `seq` and `map` combined but
without any arrays.
- `Parsimmon.alt(p1, p2, ... pn)` accepts a variable number of parsers,
and yields the value of the first one that succeeds, backtracking in between.
- `Parsimmon.lazy(f)` accepts a function that returns a parser, which
is evaluated the first time the parser is used. This is useful for
referencing parsers that haven't yet been defined.
- `Parsimmon.sepBy(content, separator)` accepts two parsers, and expects multiple
`content`s, separated by `separator`s. Yields an array of `contents`.
- `Parsimmon.sepBy1(content, separator)` same as `Parsimmon.sepBy`, but expects
`content` to succeed at least once.
- `Parsimmon.lazy(f)` accepts a function that returns a parser, which is
evaluated the first time the parser is used. This is useful for
referencing parsers that haven't yet been defined, and for implementing
recursive parsers.
- `Parsimmon.lazy(desc, f)` is the same as `Parsimmon.lazy` but also

@@ -105,4 +122,6 @@ sets `desc` as the expected value (see `.desc()` below)

- `Parsimmon.eof` expects the end of the stream.
- `Parsimmon.index` is a parser that yields the current index of the parse.
- `Parsimmon.test(pred)` yield a single characer if it passes the predicate.
- `Parsimmon.index` is a parser that yields an object an object representing
the current offset into the parse: it has a 0-based character `offset`
property and 1-based `line` and `column` properties.
- `Parsimmon.test(pred)` yield a single character if it passes the predicate.
- `Parsimmon.takeWhile(pred)` yield a string containing all the next characters that pass the predicate.

@@ -167,5 +186,7 @@

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.
- `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 are objects with a 0-based `offset` and 1-based `line` and
`column` properties that represent the position in the stream that
contained the parsed text.
- `parser.desc(description)` returns a new parser whose failure message is the passed

@@ -177,3 +198,3 @@ description. For example, `string('x').desc('the letter x')` will indicate that

These apply to most parsers for traditional langauges - it's possible
These apply to most parsers for traditional languages - it's possible
you may need to do something different for yours!

@@ -187,3 +208,3 @@

``` js
```javascript
var ignore = whitespace.or(comment.many());

@@ -195,3 +216,3 @@ function lexeme(p) { return p.skip(ignore); }

``` js
```javascript
var lparen = lexeme(string('('));

@@ -202,14 +223,17 @@ var rparen = lexeme(string(')'));

1. Forward-declare one or more top-level expressions with `lazy`,
referring to parsers that have not yet been defined. Generally, this
takes the form of a large `.alt()` call
1. Forward-declare one or more top-level expressions with `lazy`, referring to
parsers that have not yet been defined. Generally, this takes the form of a
large `.alt()` call
``` js
```javascript
var expr = lazy('an expression', function() { return Parsimmon.alt(p1, p2, ...); });
```
With `.lazy` you could also recursively refer to `expr` in its own
definition.
1. Then build your parsers from the inside out - these should return
AST nodes or other objects specific to your domain.
``` js
```javascript
var p1 = ...

@@ -222,3 +246,3 @@ var p2 = ...

``` js
```javascript
return ignore.then(expr.many());

@@ -225,0 +249,0 @@ ```

@@ -56,5 +56,18 @@ var Parsimmon = {};

// For ensuring we have the right argument types
function assertParser(p) {
if (!(p instanceof Parser)) throw new Error('not a parser: '+p);
}
function assertNumber(x) {
if (typeof x !== 'number') throw new Error('not a number: '+x);
}
function assertRegexp(x) {
if (!(x instanceof RegExp)) throw new Error('not a regex: '+x);
}
function assertFunction(x) {
if (typeof x !== 'function') throw new Error('not a function: '+x);
}
function assertString(x) {
if (typeof x !== 'string') throw new Error('not a string: '+x)
}

@@ -68,3 +81,4 @@ function formatExpected(expected) {

function formatGot(stream, error) {
var i = error.index;
var index = error.index;
var i = index.offset;

@@ -77,3 +91,4 @@ if (i === stream.length) return ', got the end of the stream'

return ' at character ' + i + ', got ' + prefix + stream.slice(i, i+12) + suffix
return ' at line ' + index.line + ' column ' + index.column
+ ', got ' + prefix + stream.slice(i, i+12) + suffix
}

@@ -86,2 +101,5 @@

_.parse = function(stream) {
if (typeof stream !== 'string') {
throw new Error('.parse must be called with a string as its argument');
}
var result = this.skip(eof)._(stream, 0);

@@ -94,3 +112,3 @@

status: false,
index: result.furthest,
index: makeLineColumnIndex(stream, result.furthest),
expected: result.expected

@@ -105,2 +123,6 @@ };

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -142,2 +164,6 @@ var result;

for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parser(function(stream, i) {

@@ -153,2 +179,20 @@ var result;

var sepBy = Parsimmon.sepBy = function(parser, separator) {
// Argument asserted by sepBy1
return sepBy1(parser, separator).or(Parsimmon.of([]));
};
var sepBy1 = Parsimmon.sepBy1 = function(parser, separator) {
assertParser(parser);
assertParser(separator);
var pairs = separator.then(parser).many();
return parser.chain(function(r) {
return pairs.map(function(rs) {
return [r].concat(rs);
})
})
};
// -*- primitive combinators -*- //

@@ -228,2 +272,5 @@ _.or = function(alternative) {

assertNumber(min);
assertNumber(max);
return Parser(function(stream, i) {

@@ -270,2 +317,5 @@ var accum = [];

_.map = function(fn) {
assertFunction(fn);
var self = this;

@@ -303,2 +353,4 @@ return Parser(function(stream, i) {

assertString(str);
return Parser(function(stream, i) {

@@ -317,2 +369,6 @@ var head = stream.slice(i, i+len);

var regex = Parsimmon.regex = function(re, group) {
assertRegexp(re);
if (group) assertNumber(group);
var anchored = RegExp('^(?:'+re.source+')', (''+re).slice((''+re).lastIndexOf('/')+1));

@@ -369,2 +425,4 @@ var expected = '' + re;

var test = Parsimmon.test = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -390,2 +448,4 @@ var char = stream.charAt(i);

var takeWhile = Parsimmon.takeWhile = function(predicate) {
assertFunction(predicate);
return Parser(function(stream, i) {

@@ -414,6 +474,22 @@ var j = i;

var index = Parsimmon.index = Parser(function(stream, i) {
return makeSuccess(i, i);
});
var makeLineColumnIndex = function(stream, i) {
var lines = stream.slice(0, i).split("\n");
// Note that unlike the character offset, the line and column offsets are
// 1-based.
var lineWeAreUpTo = lines.length;
var columnWeAreUpTo = lines[lines.length - 1].length + 1;
return {
offset: i,
line: lineWeAreUpTo,
column: columnWeAreUpTo
};
};
var index
= Parsimmon.index
= Parser(function(stream, i) {
return makeSuccess(i, makeLineColumnIndex(stream, i));
});
//- fantasyland compat

@@ -420,0 +496,0 @@

@@ -22,11 +22,19 @@ suite('parser', function() {

res = parser.parse('y')
assert.ok(!res.status)
assert.equal("'x'", res.expected);
assert.equal(0, res.index);
res = parser.parse('y');
assert.deepEqual(res, {
status: false,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ["'x'"]
});
assert.equal(
"expected 'x' at character 0, got 'y'",
"expected 'x' at line 1 column 1, got 'y'",
Parsimmon.formatError('y', res)
);
assert.throws(function() { string(34) });
});

@@ -41,3 +49,7 @@

status: false,
index: 0,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ['/[0-9]/']

@@ -47,5 +59,11 @@ });

status: false,
index: 1,
index: {
offset: 1,
line: 1,
column: 2
},
expected: ['EOF']
});
assert.throws(function() { regex(42) });
assert.throws(function() { regex(/a/, 'not a number') });
});

@@ -68,3 +86,7 @@

status: false,
index: 7,
index: {
offset: 7,
line: 1,
column: 8
},
expected: ["')'", "/[^\\)]/"]

@@ -74,5 +96,10 @@ });

status: false,
index: 0,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ["'('"]
});
assert.throws(function() { seq('not a parser') });
});

@@ -107,3 +134,11 @@

assert.deepEqual(failer().parse('a'), {status: false, index: 0, expected: ['nothing']})
assert.deepEqual(failer().parse('a'), {
status: false,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ['nothing']}
)
});

@@ -153,4 +188,56 @@

});
})
assert.throws(function() { alt('not a parser') });
});
suite('Parsimmon.sepBy/sepBy1', function() {
var chars = regex(/[a-zA-Z]+/);
var comma = string(',');
var csvSep = Parsimmon.sepBy(chars, comma);
var csvSep1 = Parsimmon.sepBy1(chars, comma);
test('successful, returns an array of parsed elements', function(){
var input = 'Heres,a,csv,string,in,our,restrictive,dialect';
var output = ['Heres', 'a', 'csv', 'string', 'in', 'our', 'restrictive', 'dialect']
assert.deepEqual(csvSep.parse(input).value, output);
assert.deepEqual(csvSep1.parse(input).value, output);
assert.throws(function() { Parsimmon.sepBy('not a parser') });
assert.throws(function() {
Parsimmon.sepBy(string('a'), 'not a parser')
});
});
test('sepBy succeeds with the empty list on empty input, sepBy1 fails', function() {
assert.deepEqual(csvSep.parse('').value, []);
assert.deepEqual(csvSep1.parse(''), {
status: false,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ['/[a-zA-Z]+/']
});
});
test('does not tolerate trailing separators', function() {
var input = 'Heres,a,csv,with,a,trailing,comma,';
var output = {
status: false,
index: {
offset: 34,
line: 1,
column: 35
},
expected: ['/[a-zA-Z]+/']
};
assert.deepEqual(csvSep.parse(input), output);
assert.deepEqual(csvSep1.parse(input), output);
});
});
suite('then', function() {

@@ -163,3 +250,7 @@ test('with a parser, uses the last return value', function() {

expected: ["'x'"],
index: 0
index: {
offset: 0,
line: 1,
column: 1
}
})

@@ -169,5 +260,14 @@ assert.deepEqual(parser.parse('xz'), {

expected: ["'y'"],
index: 1
index: {
offset: 1,
line: 1,
column: 2
}
});
});
test('errors when argument is not a parser', function() {
assert.throws(function() {
string('x').then('not a parser')
});
});
});

@@ -208,2 +308,5 @@

});
test('asserts that a function was given', function() {
assert.throws(function() { string('x').map('not a function') });
});
});

@@ -225,2 +328,5 @@

});
test('asserts that a parser was given', function() {
assert.throws(function() { string('x').skip('not a parser') });
});
});

@@ -247,2 +353,5 @@

});
test('asserts that a parser was given', function() {
assert.throws(function() { string('x').or('not a parser') });
});
});

@@ -326,2 +435,8 @@

});
test('checks that argument types are correct', function() {
assert.throws(function() { string('x').times('not a number') });
assert.throws(function() { string('x').times(1, 'not a number') });
assert.throws(function() { string('x').atLeast('not a number') });
assert.throws(function() { string('x').atMost('not a number') });
});
});

@@ -340,3 +455,7 @@

status: false,
index: 1,
index: {
offset: 1,
line: 1,
column: 2
},
expected: ['a character besides y']

@@ -364,3 +483,7 @@ });

status: false,
index: 2,
index: {
offset: 2,
line: 1,
column: 3
},
expected: ['+']

@@ -373,3 +496,7 @@ });

status: false,
index: 2,
index: {
offset: 2,
line: 1,
column: 3
},
expected: ['*']

@@ -391,2 +518,3 @@ });

assert.equal(parser.parse('.').status, false);
assert.throws(function() { Parsimmon.test('not a function') });
});

@@ -401,9 +529,22 @@

assert.equal(parser.parse('').value, '');
assert.throws(function() { Parsimmon.takeWhile('not a function') });
});
test('index', function() {
var parser = regex(/^x*/).then(index);
assert.equal(parser.parse('').value, 0);
assert.equal(parser.parse('xx').value, 2);
assert.equal(parser.parse('xxxx').value, 4);
var parser = regex(/^[x\n]*/).then(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
});
});

@@ -414,4 +555,26 @@

var parser = optWhitespace.then(ys).skip(optWhitespace);
assert.deepEqual(parser.parse('').value, { start: 0, value: '', end: 0 });
assert.deepEqual(parser.parse(' yy ').value, { start: 1, value: 'yy', end: 3 });
assert.deepEqual(
parser.parse('').value,
{
value: '',
start: { offset: 0, line: 1, column: 1 },
end: { offset: 0, line: 1, column: 1 }
}
);
assert.deepEqual(
parser.parse(' yy ').value,
{
value: 'yy',
start: { offset: 1, line: 1, column: 2 },
end: { offset: 3, line: 1, column: 4 }
}
);
assert.deepEqual(
parser.parse('\nyy ').value,
{
value: 'yy',
start: { offset: 1, line: 2, column: 1 },
end: { offset: 3, line: 2, column: 3 }
}
);
});

@@ -429,3 +592,7 @@

status: false,
index: 3,
index: {
offset: 3,
line: 1,
column: 4
},
expected: ["'def'"]

@@ -440,3 +607,7 @@ });

status: false,
index: 3,
index: {
offset: 3,
line: 1,
column: 4
},
expected: ["'d'", "'def'"]

@@ -452,3 +623,7 @@ });

status: false,
index: 6,
index: {
offset: 6,
line: 1,
column: 7
},
expected: ["'g'"]

@@ -472,3 +647,7 @@ });

status: false,
index: 10,
index: {
offset: 10,
line: 1,
column: 11
},
expected: ['EOF', "'('", "an atom"]

@@ -479,3 +658,7 @@ });

status: false,
index: 13,
index: {
offset: 13,
line: 1,
column: 14
},
expected: ["')'", "'('", "an atom"]

@@ -493,3 +676,7 @@ });

status: false,
index: 5,
index: {
offset: 5,
line: 1,
column: 6
},
expected: ["'def'"]

@@ -506,3 +693,7 @@ });

status: false,
index: 4,
index: {
offset: 4,
line: 1,
column: 5
},
expected: ["'def'"]

@@ -513,3 +704,7 @@ });

status: false,
index: 7,
index: {
offset: 7,
line: 1,
column: 8
},
expected: ["'def'"]

@@ -528,3 +723,7 @@ });

status: false,
index: 0,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ['the letter x']

@@ -535,3 +734,7 @@ });

status: false,
index: 1,
index: {
offset: 1,
line: 1,
column: 2
},
expected: ['the letter y']

@@ -548,3 +751,7 @@ });

status: false,
index: 0,
index: {
offset: 0,
line: 1,
column: 1
},
expected: ['the letter x']

@@ -555,3 +762,7 @@ });

status: false,
index: 1,
index: {
offset: 1,
line: 1,
column: 2
},
expected: ['the letter y']

@@ -558,0 +769,0 @@ });

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc