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 1.5.0 to 1.6.0

build/parsimmon.umd.min.js

6

CHANGELOG.md

@@ -0,3 +1,9 @@

## version 1.6.0 (2017-06-26)
* Adds `Parsimmon.seqObj(...args)`
## version 1.5.0 (2017-06-17)
NOTE: Code was completed on 2017-06-17, but due to human error, was not published on npm until 2017-06-26.
* Adds `parser.sepBy(separator)` alias for `Parsimmon.sepBy(parser, separator)`

@@ -4,0 +10,0 @@ * Adds `parser.sepBy1(separator)` alias for `Parsimmon.sepBy1(parser, separator)`

15

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

@@ -20,5 +20,4 @@ "keywords": [

"main": "src/parsimmon.js",
"browser": "build/parsimmon.browser.min.js",
"browser": "build/parsimmon.umd.min.js",
"devDependencies": {
"chai": "^3.5.0",
"eslint": "^3.6.0",

@@ -29,3 +28,3 @@ "mkdirp": "^0.5.1",

"rimraf": "^2.5.4",
"uglify-js": "2.x"
"webpack": "^2.6.1"
},

@@ -35,5 +34,3 @@ "license": "MIT",

"prebuild": "rimraf build && mkdirp build",
"build": "npm run build:browser && npm run build:browser.min",
"build:browser": "ncp src/parsimmon.js build/parsimmon.browser.js",
"build:browser.min": "uglifyjs --mangle < src/parsimmon.js > build/parsimmon.browser.min.js",
"build": "webpack -p",
"prepublishOnly": "npm run test && npm run build",

@@ -43,5 +40,5 @@ "lint": "eslint .",

"pretest": "npm run lint",
"test": "mocha --ui tdd --reporter dot test/intro.js test/*.test.js",
"watch:test": "mocha --ui tdd --reporter min --watch test/intro.js test/*.test.js"
"test": "mocha --ui tdd --reporter dot test/setup.js test/core/*.test.js test/laws/*.test.js",
"watch:test": "mocha --ui tdd --reporter min --watch test/setup.js test/core/*.test.js test/laws/*.test.js"
}
}

24

README.md

@@ -15,2 +15,22 @@ <a href="https://travis-ci.org/jneen/parsimmon"><img alt="Build Status" src="https://api.travis-ci.org/jneen/parsimmon.svg"></a>

<!--
Parsimmon is officially tested against Node.js 4.x and higher. It should also work in [browsers with ES5 support][es5] (IE9* and up).
If you need IE8 support, you may be able to get Parsimmon to work by using [es5-shim][], but this is **not officially supported**. Alternately, you can use an older version of Parsimmon which supports IE8.
\* _IE9 does not support "strict mode", but Parsimmon does not require it._
## Module usage
```
npm install --save parsimmon
```
## Browser usage
To download the latest browser build, use the [unpkg version][]. Parsimmon is exposed as a global variable called `Parsimmon`. For more information on how to use unpkg, see the [unpkg homepage][].
-->
## API Documentation

@@ -84,3 +104,3 @@

Parsimmon is also compatible with [fantasyland][]. It is a Semigroup, an Applicative Functor, and a Monad.
Parsimmon is also compatible with [fantasyland][]. It implements Semigroup, Apply, Applicative, Functor, Chain, and Monad.

@@ -103,1 +123,3 @@ [@bd82]: https://github.com/bd82

[perf]: https://sap.github.io/chevrotain/performance/
[es5]: https://kangax.github.io/compat-table/es5/
[es5-shim]: https://github.com/es-shims/es5-shim

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

/* global module, define */
'use strict';
// This unsightly UMD-module header is here to make this code work without
// modification with CommonJS, AMD, and browser globals.
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window).
root.Parsimmon = factory();
function Parsimmon(action) {
if (!(this instanceof Parsimmon)) {
return new Parsimmon(action);
}
}(this, function() {
'use strict';
this._ = action;
}
// The Parser object is a wrapper for a parser function.
// Externally, you use one to parse a string by calling
// var result = SomeParser.parse('Me Me Me! Parse Me!');
// You should never call the constructor, rather you should
// construct your Parser from the base parsers and the
// parser combinator methods.
function Parsimmon(action) {
if (!(this instanceof Parsimmon)) {
return new Parsimmon(action);
}
this._ = action;
}
var _ = Parsimmon.prototype;
function isParser(obj) {
return obj instanceof Parsimmon;
}
// -*- Helpers -*-
var _ = Parsimmon.prototype;
function isParser(obj) {
return obj instanceof Parsimmon;
}
function makeSuccess(index, value) {
return {
status: true,
index: index,
value: value,
furthest: -1,
expected: []
};
}
function isArray(x) {
return {}.toString.call(x) === '[object Array]';
}
function makeFailure(index, expected) {
return {
status: false,
index: -1,
value: null,
furthest: index,
expected: [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 mergeReplies(result, last) {
if (!last) {
return result;
}
if (result.furthest > last.furthest) {
return result;
}
var expected = (result.furthest === last.furthest)
? unsafeUnion(result.expected, last.expected)
: last.expected;
return {
status: result.status,
index: result.index,
value: result.value,
furthest: last.furthest,
expected: expected
};
}
function mergeReplies(result, last) {
if (!last) {
return result;
}
if (result.furthest > last.furthest) {
return result;
}
var expected = (result.furthest === last.furthest)
? unsafeUnion(result.expected, last.expected)
: last.expected;
return {
status: result.status,
index: result.index,
value: result.value,
furthest: last.furthest,
expected: expected
};
function makeLineColumnIndex(input, i) {
var lines = input.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
};
}
// Returns the sorted set union of two arrays of strings. Note that if both
// arrays are empty, it simply returns the first array, and if exactly one
// array is empty, it returns the other one unsorted. This is safe because
// expectation arrays always start as [] or [x], so as long as we merge with
// this function, we know they stay in sorted order.
function unsafeUnion(xs, ys) {
// Exit early if either array is empty (common case)
var xn = xs.length;
var yn = ys.length;
if (xn === 0) {
return ys;
} else if (yn === 0) {
return xs;
}
// Returns the sorted set union of two arrays of strings. Note that if both
// arrays are empty, it simply returns the first array, and if exactly one
// array is empty, it returns the other one unsorted. This is safe because
// expectation arrays always start as [] or [x], so as long as we merge with
// this function, we know they stay in sorted order.
function unsafeUnion(xs, ys) {
// Exit early if either array is empty (common case)
var xn = xs.length;
var yn = ys.length;
if (xn === 0) {
return ys;
} else if (yn === 0) {
return xs;
// Two non-empty arrays: do the full algorithm
var obj = {};
for (var i = 0; i < xn; i++) {
obj[xs[i]] = true;
}
for (var j = 0; j < yn; j++) {
obj[ys[j]] = true;
}
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
// Two non-empty arrays: do the full algorithm
var obj = {};
for (var i = 0; i < xn; i++) {
obj[xs[i]] = true;
}
for (var j = 0; j < yn; j++) {
obj[ys[j]] = true;
}
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
keys.sort();
return keys;
}
keys.sort();
return keys;
}
// For ensuring we have the right argument types
function assertParser(p) {
if (!isParser(p)) {
throw new Error('not a parser: ' + p);
}
function assertParser(p) {
if (!isParser(p)) {
throw new Error('not a parser: ' + p);
}
}
// TODO: Switch to Array.isArray eventually.
function assertArray(x) {
if ({}.toString.call(x) !== '[object Array]') {
throw new Error('not an array: ' + x);
}
// TODO[ES5]: Switch to Array.isArray eventually.
function assertArray(x) {
if (!isArray(x)) {
throw new Error('not an array: ' + x);
}
}
function assertNumber(x) {
if (typeof x !== 'number') {
throw new Error('not a number: ' + x);
}
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 regexp: '+x);
}
var f = flags(x);
for (var i = 0; i < f.length; i++) {
var c = f.charAt(i);
// Only allow regexp flags [imu] for now, since [g] and [y] specifically
// mess up Parsimmon. If more non-stateful regexp flags are added in the
// future, this will need to be revisited.
if (c != 'i' && c != 'm' && c != 'u') {
throw new Error('unsupported regexp flag "' + c + '": ' + x);
}
}
function assertRegexp(x) {
if (!(x instanceof RegExp)) {
throw new Error('not a regexp: '+x);
}
function assertFunction(x) {
if (typeof x !== 'function') {
throw new Error('not a function: ' + x);
var f = flags(x);
for (var i = 0; i < f.length; i++) {
var c = f.charAt(i);
// Only allow regexp flags [imu] for now, since [g] and [y] specifically
// mess up Parsimmon. If more non-stateful regexp flags are added in the
// future, this will need to be revisited.
if (c !== 'i' && c !== 'm' && c !== 'u') {
throw new Error('unsupported regexp flag "' + c + '": ' + x);
}
}
}
function assertString(x) {
if (typeof x !== 'string') {
throw new Error('not a string: ' + x);
}
function assertFunction(x) {
if (typeof x !== 'function') {
throw new Error('not a function: ' + x);
}
}
function formatExpected(expected) {
if (expected.length === 1) {
return expected[0];
}
return 'one of ' + expected.join(', ');
function assertString(x) {
if (typeof x !== 'string') {
throw new Error('not a string: ' + x);
}
}
function formatGot(input, error) {
var index = error.index;
var i = index.offset;
if (i === input.length) {
return ', got the end of the input';
}
var prefix = (i > 0 ? '\'...' : '\'');
var suffix = (input.length - i > 12 ? '...\'' : '\'');
return ' at line ' + index.line + ' column ' + index.column
+ ', got ' + prefix + input.slice(i, i + 12) + suffix;
function formatExpected(expected) {
if (expected.length === 1) {
return expected[0];
}
return 'one of ' + expected.join(', ');
}
function formatError(input, error) {
return 'expected ' +
formatExpected(error.expected) +
formatGot(input, error);
function formatGot(input, error) {
var index = error.index;
var i = index.offset;
if (i === input.length) {
return ', got the end of the input';
}
var prefix = (i > 0 ? '\'...' : '\'');
var suffix = (input.length - i > 12 ? '...\'' : '\'');
return ' at line ' + index.line + ' column ' + index.column
+ ', got ' + prefix + input.slice(i, i + 12) + suffix;
}
_.parse = function(input) {
if (typeof input !== 'string') {
throw new Error('.parse must be called with a string as its argument');
}
var result = this.skip(eof)._(input, 0);
function formatError(input, error) {
return 'expected ' +
formatExpected(error.expected) +
formatGot(input, error);
}
return result.status ? {
status: true,
value: result.value
} : {
status: false,
index: makeLineColumnIndex(input, result.furthest),
expected: result.expected
};
};
function flags(re) {
var s = '' + re;
return s.slice(s.lastIndexOf('/') + 1);
}
_.tryParse = function(str) {
var result = this.parse(str);
if (result.status) {
return result.value;
} else {
var msg = formatError(str, result);
var err = new Error(msg);
err.type = 'ParsimmonError';
err.result = result;
throw err;
}
};
function anchoredRegexp(re) {
return RegExp('^(?:' + re.source + ')', flags(re));
}
// [Parsimmon a] -> Parsimmon [a]
function seq() {
var parsers = [].slice.call(arguments);
var numParsers = parsers.length;
// -*- Combinators -*-
function seq() {
var parsers = [].slice.call(arguments);
var numParsers = parsers.length;
for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parsimmon(function(input, i) {
var result;
var accum = new Array(numParsers);
for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
result = mergeReplies(parsers[j]._(input, i), result);
if (!result.status) {
return result;
}
accum[j] = result.value;
i = result.index;
}
return Parsimmon(function(input, i) {
var result;
var accum = new Array(numParsers);
for (var j = 0; j < numParsers; j += 1) {
result = mergeReplies(parsers[j]._(input, i), result);
if (!result.status) {
return result;
return mergeReplies(makeSuccess(i, accum), result);
});
}
function seqObj() {
var seenKeys = {};
var totalKeys = 0;
var parsers = [].slice.call(arguments);
var numParsers = parsers.length;
for (var j = 0; j < numParsers; j += 1) {
var p = parsers[j];
if (isParser(p)) {
continue;
}
if (isArray(p)) {
var isWellFormed =
p.length === 2 &&
typeof p[0] === 'string' &&
isParser(p[1]);
if (isWellFormed) {
var key = p[0];
if (seenKeys[key]) {
throw new Error('seqObj: duplicate key ' + key);
}
accum[j] = result.value;
i = result.index;
seenKeys[key] = true;
totalKeys++;
continue;
}
return mergeReplies(makeSuccess(i, accum), result);
});
}
function seqMap() {
var args = [].slice.call(arguments);
if (args.length === 0) {
throw new Error('seqMap needs at least one argument');
}
var mapper = args.pop();
assertFunction(mapper);
return seq.apply(null, args).map(function(results) {
return mapper.apply(null, results);
});
throw new Error(
'seqObj arguments must be parsers or ' +
'[string, parser] array pairs.'
);
}
// Revisit this with Object.keys and .bind when we drop ES3 support.
function createLanguage(parsers) {
var language = {};
for (var key in parsers) {
if ({}.hasOwnProperty.call(parsers, key)) {
(function(key) {
var func = function() {
return parsers[key](language);
};
language[key] = lazy(func);
}(key));
if (totalKeys === 0) {
throw new Error('seqObj expects at least one named parser, found zero');
}
return Parsimmon(function(input, i) {
var result;
var accum = {};
for (var j = 0; j < numParsers; j += 1) {
var name;
var parser;
if (isArray(parsers[j])) {
name = parsers[j][0];
parser = parsers[j][1];
} else {
name = null;
parser = parsers[j];
}
result = mergeReplies(parser._(input, i), result);
if (!result.status) {
return result;
}
if (name) {
accum[name] = result.value;
}
i = result.index;
}
return language;
}
return mergeReplies(makeSuccess(i, accum), result);
});
}
/**
* Allows to add custom primitive parsers
*/
function custom(parsingFunction) {
return Parsimmon(parsingFunction(makeSuccess, makeFailure));
function seqMap() {
var args = [].slice.call(arguments);
if (args.length === 0) {
throw new Error('seqMap needs at least one argument');
}
var mapper = args.pop();
assertFunction(mapper);
return seq.apply(null, args).map(function(results) {
return mapper.apply(null, results);
});
}
function alt() {
var parsers = [].slice.call(arguments);
var numParsers = parsers.length;
if (numParsers === 0) {
return fail('zero alternates');
// TODO[ES5]: Revisit this with Object.keys and .bind.
function createLanguage(parsers) {
var language = {};
for (var key in parsers) {
if ({}.hasOwnProperty.call(parsers, key)) {
(function(key) {
var func = function() {
return parsers[key](language);
};
language[key] = lazy(func);
}(key));
}
for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parsimmon(function(input, i) {
var result;
for (var j = 0; j < parsers.length; j += 1) {
result = mergeReplies(parsers[j]._(input, i), result);
if (result.status) return result;
}
return result;
});
}
return language;
}
function sepBy(parser, separator) {
// Argument asserted by sepBy1
return sepBy1(parser, separator).or(succeed([]));
function alt() {
var parsers = [].slice.call(arguments);
var numParsers = parsers.length;
if (numParsers === 0) {
return fail('zero alternates');
}
for (var j = 0; j < numParsers; j += 1) {
assertParser(parsers[j]);
}
return Parsimmon(function(input, i) {
var result;
for (var j = 0; j < parsers.length; j += 1) {
result = mergeReplies(parsers[j]._(input, i), result);
if (result.status) {
return result;
}
}
return result;
});
}
function sepBy1(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);
});
function sepBy(parser, separator) {
// Argument asserted by sepBy1
return sepBy1(parser, separator).or(succeed([]));
}
function sepBy1(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 -*- //
_.or = function(alternative) {
return alt(this, alternative);
};
// -*- Core Parsing Methods -*-
_.trim = function(parser) {
return this.wrap(parser, parser);
_.parse = function(input) {
if (typeof input !== 'string') {
throw new Error('.parse must be called with a string as its argument');
}
var result = this.skip(eof)._(input, 0);
if (result.status) {
return {
status: true,
value: result.value
};
}
return {
status: false,
index: makeLineColumnIndex(input, result.furthest),
expected: result.expected
};
};
_.wrap = function(leftParser, rightParser) {
return seqMap(
leftParser,
this,
rightParser,
function(left, middle) {
return middle;
}
);
};
// -*- Other Methods -*-
_.thru = function(wrapper) {
return wrapper(this);
};
_.tryParse = function(str) {
var result = this.parse(str);
if (result.status) {
return result.value;
} else {
var msg = formatError(str, result);
var err = new Error(msg);
err.type = 'ParsimmonError';
err.result = result;
throw err;
}
};
_.then = function(next) {
if (typeof next === 'function') {
throw new Error('chaining features of .then are no longer supported, use .chain instead');
_.or = function(alternative) {
return alt(this, alternative);
};
_.trim = function(parser) {
return this.wrap(parser, parser);
};
_.wrap = function(leftParser, rightParser) {
return seqMap(
leftParser,
this,
rightParser,
function(left, middle) {
return middle;
}
assertParser(next);
return seq(this, next).map(function(results) { return results[1]; });
};
);
};
// -*- optimized iterative combinators -*- //
// equivalent to:
// _.many = function() {
// return this.times(0, Infinity);
// };
// or, more explicitly:
// _.many = function() {
// var self = this;
// return self.then(function(x) {
// return self.many().then(function(xs) {
// return [x].concat(xs);
// });
// }).or(succeed([]));
// };
_.many = function() {
var self = this;
_.thru = function(wrapper) {
return wrapper(this);
};
return Parsimmon(function(input, i) {
var accum = [];
var result = undefined;
_.then = function(next) {
assertParser(next);
return seq(this, next).map(function(results) { return results[1]; });
};
for (;;) {
result = mergeReplies(self._(input, i), result);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
return mergeReplies(makeSuccess(i, accum), result);
}
}
});
};
_.many = function() {
var self = this;
_.tie = function() {
return this.map(function(args) {
assertArray(args);
var s = '';
for (var i = 0; i < args.length; i++) {
assertString(args[i]);
s += args[i];
return Parsimmon(function(input, i) {
var accum = [];
var result = undefined;
for (;;) {
result = mergeReplies(self._(input, i), result);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
return mergeReplies(makeSuccess(i, accum), result);
}
return s;
});
};
}
});
};
// equivalent to:
// _.times = function(min, max) {
// if (arguments.length < 2) max = min;
// var self = this;
// if (min > 0) {
// return self.then(function(x) {
// return self.times(min - 1, max - 1).then(function(xs) {
// return [x].concat(xs);
// });
// });
// }
// else if (max > 0) {
// return self.then(function(x) {
// return self.times(0, max - 1).then(function(xs) {
// return [x].concat(xs);
// });
// }).or(succeed([]));
// }
// else return succeed([]);
// };
_.times = function(min, max) {
var self = this;
if (arguments.length < 2) {
max = min;
_.tie = function() {
return this.map(function(args) {
assertArray(args);
var s = '';
for (var i = 0; i < args.length; i++) {
assertString(args[i]);
s += args[i];
}
assertNumber(min);
assertNumber(max);
return Parsimmon(function(input, i) {
var accum = [];
var result = undefined;
var prevResult = undefined;
for (var times = 0; times < min; times += 1) {
result = self._(input, i);
prevResult = mergeReplies(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
return prevResult;
}
return s;
});
};
_.times = function(min, max) {
var self = this;
if (arguments.length < 2) {
max = min;
}
assertNumber(min);
assertNumber(max);
return Parsimmon(function(input, i) {
var accum = [];
var result = undefined;
var prevResult = undefined;
for (var times = 0; times < min; times += 1) {
result = self._(input, i);
prevResult = mergeReplies(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
return prevResult;
}
for (; times < max; times += 1) {
result = self._(input, i);
prevResult = mergeReplies(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
break;
}
}
for (; times < max; times += 1) {
result = self._(input, i);
prevResult = mergeReplies(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
} else {
break;
}
return mergeReplies(makeSuccess(i, accum), prevResult);
});
};
}
return mergeReplies(makeSuccess(i, accum), prevResult);
});
};
// -*- higher-level combinators -*- //
_.result = function(res) {
return this.map(function() {
return res;
});
};
_.result = function(res) {
return this.map(function() {
return res;
});
};
_.atMost = function(n) {
return this.times(0, n);
};
_.atMost = function(n) {
return this.times(0, n);
};
_.atLeast = function(n) {
return seqMap(this.times(n), this.many(), function(init, rest) {
return init.concat(rest);
});
};
_.atLeast = function(n) {
return seqMap(this.times(n), this.many(), function(init, rest) {
return init.concat(rest);
});
};
_.map = function(fn) {
assertFunction(fn);
var self = this;
return Parsimmon(function(input, i) {
var result = self._(input, i);
if (!result.status) {
return result;
}
return mergeReplies(makeSuccess(result.index, fn(result.value)), result);
});
};
_['fantasy-land/map'] = _.map;
_.map = function(fn) {
assertFunction(fn);
var self = this;
return Parsimmon(function(input, i) {
var result = self._(input, i);
if (!result.status) {
return result;
}
return mergeReplies(makeSuccess(result.index, fn(result.value)), result);
});
};
_.skip = function(next) {
return seq(this, next).map(function(results) { return results[0]; });
};
_.skip = function(next) {
return seq(this, next).map(function(results) { return results[0]; });
};
_.mark = function() {
return seqMap(index, this, index, function(start, value, end) {
return {
start: start,
value: value,
end: end
};
});
};
_.mark = function() {
return seqMap(index, this, index, function(start, value, end) {
return {
start: start,
value: value,
end: end
};
});
};
_.node = function(name) {
return seqMap(index, this, index, function(start, value, end) {
return {
name: name,
value: value,
start: start,
end: end
};
});
};
_.node = function(name) {
return seqMap(index, this, index, function(start, value, end) {
return {
name: name,
value: value,
start: start,
end: end
};
});
};
_.sepBy = function(separator) {
return sepBy(this, separator);
};
_.sepBy = function(separator) {
return sepBy(this, separator);
};
_.sepBy1 = function(separator) {
return sepBy1(this, separator);
};
_.sepBy1 = function(separator) {
return sepBy1(this, separator);
};
_.lookahead = function(x) {
return this.skip(lookahead(x));
};
_.lookahead = function(x) {
return this.skip(lookahead(x));
};
_.notFollowedBy = function(x) {
return this.skip(notFollowedBy(x));
};
_.notFollowedBy = function(x) {
return this.skip(notFollowedBy(x));
};
_.desc = function(expected) {
var self = this;
return Parsimmon(function(input, i) {
var reply = self._(input, i);
if (!reply.status) {
reply.expected = [expected];
}
return reply;
});
};
_.desc = function(expected) {
var self = this;
return Parsimmon(function(input, i) {
var reply = self._(input, i);
if (!reply.status) {
reply.expected = [expected];
}
return reply;
});
};
_.fallback = function(result) {
return this.or(succeed(result));
};
_.fallback = function(result) {
return this.or(succeed(result));
};
// -*- primitive parsers -*- //
function string(str) {
assertString(str);
var expected = '\'' + str + '\'';
return Parsimmon(function(input, i) {
var j = i + str.length;
var head = input.slice(i, j);
if (head === str) {
return makeSuccess(j, head);
} else {
return makeFailure(i, expected);
}
});
}
_.ap = function(other) {
return seqMap(other, this, function(f, x) {
return f(x);
});
};
function flags(re) {
var s = '' + re;
return s.slice(s.lastIndexOf('/') + 1);
}
_.chain = function(f) {
var self = this;
return Parsimmon(function(input, i) {
var result = self._(input, i);
if (!result.status) {
return result;
}
var nextParser = f(result.value);
return mergeReplies(nextParser._(input, result.index), result);
});
};
function anchoredRegexp(re) {
return RegExp('^(?:' + re.source + ')', flags(re));
}
// -*- Constructors -*-
function regexp(re, group) {
assertRegexp(re);
if (arguments.length >= 2) {
assertNumber(group);
function string(str) {
assertString(str);
var expected = '\'' + str + '\'';
return Parsimmon(function(input, i) {
var j = i + str.length;
var head = input.slice(i, j);
if (head === str) {
return makeSuccess(j, head);
} else {
group = 0;
}
var anchored = anchoredRegexp(re);
var expected = '' + re;
return Parsimmon(function(input, i) {
var match = anchored.exec(input.slice(i));
if (match) {
var fullMatch = match[0];
var groupMatch = match[group];
if (groupMatch != null) {
return makeSuccess(i + fullMatch.length, groupMatch);
}
}
return makeFailure(i, expected);
});
}
function succeed(value) {
return Parsimmon(function(input, i) {
return makeSuccess(i, value);
});
}
function fail(expected) {
return Parsimmon(function(input, i) {
return makeFailure(i, expected);
});
}
function lookahead(x) {
if (isParser(x)) {
return Parsimmon(function(input, i) {
var result = x._(input, i);
result.index = i;
result.value = '';
return result;
});
} else if (typeof x === 'string') {
return lookahead(string(x));
} else if (x instanceof RegExp) {
return lookahead(regexp(x));
}
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);
});
function regexp(re, group) {
assertRegexp(re);
if (arguments.length >= 2) {
assertNumber(group);
} else {
group = 0;
}
var any = Parsimmon(function(input, i) {
if (i >= input.length) {
return makeFailure(i, 'any character');
var anchored = anchoredRegexp(re);
var expected = '' + re;
return Parsimmon(function(input, i) {
var match = anchored.exec(input.slice(i));
if (match) {
var fullMatch = match[0];
var groupMatch = match[group];
if (groupMatch !== null) {
return makeSuccess(i + fullMatch.length, groupMatch);
}
}
return makeSuccess(i+1, input.charAt(i));
return makeFailure(i, expected);
});
}
var all = Parsimmon(function(input, i) {
return makeSuccess(input.length, input.slice(i));
function succeed(value) {
return Parsimmon(function(input, i) {
return makeSuccess(i, value);
});
}
var eof = Parsimmon(function(input, i) {
if (i < input.length) {
return makeFailure(i, 'EOF');
}
return makeSuccess(i, null);
function fail(expected) {
return Parsimmon(function(input, i) {
return makeFailure(i, expected);
});
}
function test(predicate) {
assertFunction(predicate);
function lookahead(x) {
if (isParser(x)) {
return Parsimmon(function(input, i) {
var char = input.charAt(i);
if (i < input.length && predicate(char)) {
return makeSuccess(i + 1, char);
} else {
return makeFailure(i, 'a character matching ' + predicate);
}
var result = x._(input, i);
result.index = i;
result.value = '';
return result;
});
} else if (typeof x === 'string') {
return lookahead(string(x));
} else if (x instanceof RegExp) {
return lookahead(regexp(x));
}
throw new Error('not a string, regexp, or parser: ' + x);
}
function oneOf(str) {
return test(function(ch) {
return str.indexOf(ch) >= 0;
});
}
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);
});
}
function noneOf(str) {
return test(function(ch) {
return str.indexOf(ch) < 0;
});
}
function test(predicate) {
assertFunction(predicate);
return Parsimmon(function(input, i) {
var char = input.charAt(i);
if (i < input.length && predicate(char)) {
return makeSuccess(i + 1, char);
} else {
return makeFailure(i, 'a character matching ' + predicate);
}
});
}
// TODO: Improve error message using JSON.stringify eventually.
function range(begin, end) {
return test(function(ch) {
return begin <= ch && ch <= end;
}).desc(begin + '-' + end);
}
function oneOf(str) {
return test(function(ch) {
return str.indexOf(ch) >= 0;
});
}
function takeWhile(predicate) {
assertFunction(predicate);
function noneOf(str) {
return test(function(ch) {
return str.indexOf(ch) < 0;
});
}
return Parsimmon(function(input, i) {
var j = i;
while (j < input.length && predicate(input.charAt(j))) {
j++;
}
return makeSuccess(j, input.slice(i, j));
});
}
function custom(parsingFunction) {
return Parsimmon(parsingFunction(makeSuccess, makeFailure));
}
function lazy(desc, f) {
if (arguments.length < 2) {
f = desc;
desc = undefined;
}
// TODO[ES5]: Improve error message using JSON.stringify eventually.
function range(begin, end) {
return test(function(ch) {
return begin <= ch && ch <= end;
}).desc(begin + '-' + end);
}
var parser = Parsimmon(function(input, i) {
parser._ = f()._;
return parser._(input, i);
});
function takeWhile(predicate) {
assertFunction(predicate);
if (desc) {
return parser.desc(desc);
} else {
return parser;
return Parsimmon(function(input, i) {
var j = i;
while (j < input.length && predicate(input.charAt(j))) {
j++;
}
}
return makeSuccess(j, input.slice(i, j));
});
}
function makeLineColumnIndex(input, i) {
var lines = input.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
};
function lazy(desc, f) {
if (arguments.length < 2) {
f = desc;
desc = undefined;
}
var index = Parsimmon(function(input, i) {
return makeSuccess(i, makeLineColumnIndex(input, i));
var parser = Parsimmon(function(input, i) {
parser._ = f()._;
return parser._(input, i);
});
function empty() {
return fail('fantasy-land/empty');
if (desc) {
return parser.desc(desc);
} else {
return parser;
}
}
// Fantasy Land Semigroup support
_.concat = _.or;
_['fantasy-land/concat'] = _.concat;
// -*- Fantasy Land Extras -*-
// Fantasy Land Semigroup and Monoid support
_.empty = empty;
_['fantasy-land/empty'] = _.empty;
function empty() {
return fail('fantasy-land/empty');
}
// Fantasy Land Applicative support
_.of = succeed;
_['fantasy-land/of'] = _.of;
_.concat = _.or;
_.empty = empty;
_.of = succeed;
_['fantasy-land/ap'] = _.ap;
_['fantasy-land/chain'] = _.chain;
_['fantasy-land/concat'] = _.concat;
_['fantasy-land/empty'] = _.empty;
_['fantasy-land/of'] = _.of;
_['fantasy-land/map'] = _.map;
// Fantasy Land Applicative support
_.ap = function(other) {
return seqMap(other, this, function(f, x) {
return f(x);
});
};
_['fantasy-land/ap'] = _.ap;
// -*- Base Parsers -*-
// Fantasy Land Monad support
_.chain = function(f) {
var self = this;
return Parsimmon(function(input, i) {
var result = self._(input, i);
if (!result.status) {
return result;
}
var nextParser = f(result.value);
return mergeReplies(nextParser._(input, result.index), result);
});
};
_['fantasy-land/chain'] = _.chain;
var index = Parsimmon(function(input, i) {
return makeSuccess(i, makeLineColumnIndex(input, i));
});
var digit = regexp(/[0-9]/).desc('a digit');
var digits = regexp(/[0-9]*/).desc('optional digits');
var letter = regexp(/[a-z]/i).desc('a letter');
var letters = regexp(/[a-z]*/i).desc('optional letters');
var optWhitespace = regexp(/\s*/).desc('optional whitespace');
var whitespace = regexp(/\s+/).desc('whitespace');
var any = Parsimmon(function(input, i) {
if (i >= input.length) {
return makeFailure(i, 'any character');
}
return makeSuccess(i + 1, input.charAt(i));
});
Parsimmon.createLanguage = createLanguage;
Parsimmon.all = all;
Parsimmon.alt = alt;
Parsimmon.any = any;
Parsimmon.custom = custom;
Parsimmon.digit = digit;
Parsimmon.digits = digits;
Parsimmon.eof = eof;
Parsimmon.fail = fail;
Parsimmon.formatError = formatError;
Parsimmon.index = index;
Parsimmon.isParser = isParser;
Parsimmon.lazy = lazy;
Parsimmon.letter = letter;
Parsimmon.letters = letters;
Parsimmon.lookahead = lookahead;
Parsimmon.notFollowedBy = notFollowedBy;
Parsimmon.makeFailure = makeFailure;
Parsimmon.makeSuccess = makeSuccess;
Parsimmon.noneOf = noneOf;
Parsimmon.oneOf = oneOf;
Parsimmon.range = range;
Parsimmon.optWhitespace = optWhitespace;
Parsimmon.Parser = Parsimmon;
Parsimmon.regex = regexp;
Parsimmon.regexp = regexp;
Parsimmon.sepBy = sepBy;
Parsimmon.sepBy1 = sepBy1;
Parsimmon.seq = seq;
Parsimmon.seqMap = seqMap;
Parsimmon.string = string;
Parsimmon.succeed = succeed;
Parsimmon.takeWhile = takeWhile;
Parsimmon.test = test;
Parsimmon.whitespace = whitespace;
var all = Parsimmon(function(input, i) {
return makeSuccess(input.length, input.slice(i));
});
// Fantasy Land Semigroup support
Parsimmon.empty = empty;
Parsimmon['fantasy-land/empty'] = empty;
var eof = Parsimmon(function(input, i) {
if (i < input.length) {
return makeFailure(i, 'EOF');
}
return makeSuccess(i, null);
});
// Fantasy Land Applicative support
Parsimmon.of = succeed;
Parsimmon['fantasy-land/of'] = succeed;
var digit = regexp(/[0-9]/).desc('a digit');
var digits = regexp(/[0-9]*/).desc('optional digits');
var letter = regexp(/[a-z]/i).desc('a letter');
var letters = regexp(/[a-z]*/i).desc('optional letters');
var optWhitespace = regexp(/\s*/).desc('optional whitespace');
var whitespace = regexp(/\s+/).desc('whitespace');
return Parsimmon;
}));
Parsimmon.all = all;
Parsimmon.alt = alt;
Parsimmon.any = any;
Parsimmon.createLanguage = createLanguage;
Parsimmon.custom = custom;
Parsimmon.digit = digit;
Parsimmon.digits = digits;
Parsimmon.empty = empty;
Parsimmon.eof = eof;
Parsimmon.fail = fail;
Parsimmon.formatError = formatError;
Parsimmon.index = index;
Parsimmon.isParser = isParser;
Parsimmon.lazy = lazy;
Parsimmon.letter = letter;
Parsimmon.letters = letters;
Parsimmon.lookahead = lookahead;
Parsimmon.makeFailure = makeFailure;
Parsimmon.makeSuccess = makeSuccess;
Parsimmon.noneOf = noneOf;
Parsimmon.notFollowedBy = notFollowedBy;
Parsimmon.of = succeed;
Parsimmon.oneOf = oneOf;
Parsimmon.optWhitespace = optWhitespace;
Parsimmon.Parser = Parsimmon;
Parsimmon.range = range;
Parsimmon.regex = regexp;
Parsimmon.regexp = regexp;
Parsimmon.sepBy = sepBy;
Parsimmon.sepBy1 = sepBy1;
Parsimmon.seq = seq;
Parsimmon.seqMap = seqMap;
Parsimmon.seqObj = seqObj;
Parsimmon.string = string;
Parsimmon.succeed = succeed;
Parsimmon.takeWhile = takeWhile;
Parsimmon.test = test;
Parsimmon.whitespace = whitespace;
Parsimmon['fantasy-land/empty'] = empty;
Parsimmon['fantasy-land/of'] = succeed;
module.exports = Parsimmon;
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