molstar
Version:
A comprehensive macromolecular library.
522 lines (521 loc) • 19 kB
JavaScript
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Koya Sakuma <koya.sakuma.work@gmail.com>
**
* Adapted from Parsimmon (https://github.com/jneen/parsimmon)
* Copyright (c) 2011-present J. Adkisson (http://jneen.net).
**/
import { __spreadArray } from "tslib";
var MonadicParser = /** @class */ (function () {
function MonadicParser(_) {
this._ = _;
}
MonadicParser.prototype.parse = function (input) {
var result = this.skip(MonadicParser.eof)._(input, 0);
if (result.status) {
return { success: true, value: result.value };
}
return { success: false, index: makeLineColumnIndex(input, result.furthest), expected: result.expected };
};
;
MonadicParser.prototype.tryParse = function (str) {
var result = this.parse(str);
if (result.success) {
return result.value;
}
else {
var msg = formatError(str, result);
var err = new Error(msg);
throw err;
}
};
MonadicParser.prototype.or = function (alternative) {
return MonadicParser.alt(this, alternative);
};
MonadicParser.prototype.trim = function (parser) {
return this.wrap(parser, parser);
};
MonadicParser.prototype.wrap = function (leftParser, rightParser) {
return seqPick(1, typeof leftParser === 'string' ? MonadicParser.string(leftParser) : leftParser, this, typeof rightParser === 'string' ? MonadicParser.string(rightParser) : rightParser);
};
MonadicParser.prototype.thru = function (wrapper) {
return wrapper(this);
};
MonadicParser.prototype.then = function (next) {
return seqPick(1, this, next);
};
MonadicParser.prototype.many = function () {
var _this = this;
return new MonadicParser(function (input, i) {
var accum = [];
var result = void 0;
while (true) {
result = mergeReplies(_this._(input, i), result);
if (result.status) {
if (i === result.index) {
throw new Error('infinite loop detected in .many() parser --- calling .many() on a parser which can accept zero characters is usually the cause');
}
i = result.index;
accum.push(result.value);
}
else {
return mergeReplies(makeSuccess(i, accum), result);
}
}
});
};
;
MonadicParser.prototype.times = function (min, _max) {
var _this = this;
var max = typeof _max === 'undefined' ? min : _max;
return new MonadicParser(function (input, i) {
var accum = [];
var result = void 0;
var prevResult = void 0;
var times;
for (times = 0; times < min; times++) {
result = _this._(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 = _this._(input, i);
prevResult = mergeReplies(result, prevResult);
if (result.status) {
i = result.index;
accum.push(result.value);
}
else {
break;
}
}
return mergeReplies(makeSuccess(i, accum), prevResult);
});
};
;
MonadicParser.prototype.result = function (res) {
return this.map(function () { return res; });
};
;
MonadicParser.prototype.atMost = function (n) {
return this.times(0, n);
};
;
MonadicParser.prototype.atLeast = function (n) {
return MonadicParser.seq(this.times(n), this.many()).map(function (r) { return __spreadArray(__spreadArray([], r[0], true), r[1], true); });
};
;
MonadicParser.prototype.map = function (f) {
var _this = this;
return new MonadicParser(function (input, i) {
var result = _this._(input, i);
if (!result.status) {
return result;
}
return mergeReplies(makeSuccess(result.index, f(result.value)), result);
});
};
MonadicParser.prototype.skip = function (next) {
return seqPick(0, this, next);
};
MonadicParser.prototype.mark = function () {
return MonadicParser.seq(MonadicParser.index, this, MonadicParser.index).map(function (r) { return ({ start: r[0], value: r[1], end: r[2] }); });
};
MonadicParser.prototype.node = function (name) {
return MonadicParser.seq(MonadicParser.index, this, MonadicParser.index).map(function (r) { return ({ name: name, start: r[0], value: r[1], end: r[2] }); });
};
;
MonadicParser.prototype.sepBy = function (separator) {
return MonadicParser.sepBy(this, separator);
};
MonadicParser.prototype.sepBy1 = function (separator) {
return MonadicParser.sepBy1(this, separator);
};
MonadicParser.prototype.lookahead = function (x) {
return this.skip(MonadicParser.lookahead(x));
};
;
MonadicParser.prototype.notFollowedBy = function (x) {
return this.skip(MonadicParser.notFollowedBy(x));
};
;
MonadicParser.prototype.desc = function (expected) {
var _this = this;
return new MonadicParser(function (input, i) {
var reply = _this._(input, i);
if (!reply.status) {
reply.expected = [expected];
}
return reply;
});
};
;
MonadicParser.prototype.fallback = function (result) {
return this.or(MonadicParser.succeed(result));
};
;
MonadicParser.prototype.ap = function (other) {
return MonadicParser.seq(other, this).map(function (_a) {
var f = _a[0], x = _a[1];
return f(x);
});
};
;
MonadicParser.prototype.chain = function (f) {
var _this = this;
return new MonadicParser(function (input, i) {
var result = _this._(input, i);
if (!result.status) {
return result;
}
var nextParser = f(result.value);
return mergeReplies(nextParser._(input, result.index), result);
});
};
;
return MonadicParser;
}());
export { MonadicParser };
(function (MonadicParser) {
function seqMap(a, b, c) {
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);
});
}
MonadicParser.seqMap = seqMap;
function createLanguage(parsers) {
var language = {};
for (var _i = 0, _a = Object.keys(parsers); _i < _a.length; _i++) {
var key = _a[_i];
(function (key) {
language[key] = lazy(function () { return parsers[key](language); });
})(key);
}
return language;
}
MonadicParser.createLanguage = createLanguage;
function seq() {
var parsers = [];
for (var _i = 0; _i < arguments.length; _i++) {
parsers[_i] = arguments[_i];
}
var numParsers = parsers.length;
return new MonadicParser(function (input, index) {
var result;
var accum = new Array(numParsers);
var i = index;
for (var j = 0; j < numParsers; j++) {
result = mergeReplies(parsers[j]._(input, i), result);
if (!result.status) {
return result;
}
accum[j] = result.value;
i = result.index;
}
return mergeReplies(makeSuccess(i, accum), result);
});
}
MonadicParser.seq = seq;
function alt() {
var parsers = [];
for (var _i = 0; _i < arguments.length; _i++) {
parsers[_i] = arguments[_i];
}
var numParsers = parsers.length;
if (numParsers === 0) {
return fail('zero alternates');
}
return new MonadicParser(function (input, i) {
var result;
for (var j = 0; j < parsers.length; j++) {
result = mergeReplies(parsers[j]._(input, i), result);
if (result.status) {
return result;
}
}
return result;
});
}
MonadicParser.alt = alt;
function sepBy(parser, separator) {
return sepBy1(parser, separator).or(succeed([]));
}
MonadicParser.sepBy = sepBy;
function sepBy1(parser, separator) {
var pairs = separator.then(parser).many();
return seq(parser, pairs).map(function (r) { return __spreadArray([r[0]], r[1], true); });
}
MonadicParser.sepBy1 = sepBy1;
function string(str) {
var expected = "'".concat(str, "'");
if (str.length === 1) {
var code_1 = str.charCodeAt(0);
return new MonadicParser(function (input, i) { return input.charCodeAt(i) === code_1 ? makeSuccess(i + 1, str) : makeFailure(i, expected); });
}
return new MonadicParser(function (input, i) {
var j = i + str.length;
if (input.slice(i, j) === str)
return makeSuccess(j, str);
else
return makeFailure(i, expected);
});
}
MonadicParser.string = string;
function flags(re) {
var s = '' + re;
return s.slice(s.lastIndexOf('/') + 1);
}
function anchoredRegexp(re) {
return RegExp('^(?:' + re.source + ')', flags(re));
}
function regexp(re, group) {
if (group === void 0) { group = 0; }
var anchored = anchoredRegexp(re);
var expected = '' + re;
return new MonadicParser(function (input, i) {
var match = anchored.exec(input.slice(i));
if (match) {
if (0 <= group && group <= match.length) {
var fullMatch = match[0];
var groupMatch = match[group];
return makeSuccess(i + fullMatch.length, groupMatch);
}
var message = "invalid match group (0 to ".concat(match.length, ") in ").concat(expected);
return makeFailure(i, message);
}
return makeFailure(i, expected);
});
}
MonadicParser.regexp = regexp;
function succeed(value) {
return new MonadicParser(function (input, i) { return makeSuccess(i, value); });
}
MonadicParser.succeed = succeed;
function fail(expected) {
return new MonadicParser(function (input, i) { return makeFailure(i, expected); });
}
MonadicParser.fail = fail;
function lookahead(x) {
if (isParser(x)) {
return new MonadicParser(function (input, i) {
var result = x._(input, i);
if (result.status) {
result.index = i;
result.value = null;
}
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);
}
MonadicParser.lookahead = lookahead;
function notFollowedBy(parser) {
return new MonadicParser(function (input, i) {
var result = parser._(input, i);
return result.status
? makeFailure(i, 'not "' + input.slice(i, result.index) + '"')
: makeSuccess(i, null);
});
}
MonadicParser.notFollowedBy = notFollowedBy;
function test(predicate) {
return new MonadicParser(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 ' + predicate);
}
});
}
MonadicParser.test = test;
function oneOf(str) {
return test(function (ch) { return str.indexOf(ch) >= 0; });
}
MonadicParser.oneOf = oneOf;
function noneOf(str) {
return test(function (ch) { return str.indexOf(ch) < 0; });
}
MonadicParser.noneOf = noneOf;
function range(begin, end) {
return test(function (ch) { return begin <= ch && ch <= end; }).desc(begin + '-' + end);
}
MonadicParser.range = range;
function takeWhile(predicate) {
return new MonadicParser(function (input, i) {
var j = i;
while (j < input.length && predicate(input.charAt(j))) {
j++;
}
return makeSuccess(j, input.slice(i, j));
});
}
MonadicParser.takeWhile = takeWhile;
function lazy(f) {
var parser = new MonadicParser(function (input, i) {
var a = f()._;
parser._ = a;
return a(input, i);
});
return parser;
}
MonadicParser.lazy = lazy;
function empty() {
return fail('empty');
}
MonadicParser.empty = empty;
MonadicParser.index = new MonadicParser(function (input, i) {
return makeSuccess(i, makeLineColumnIndex(input, i));
});
MonadicParser.anyChar = new MonadicParser(function (input, i) {
if (i >= input.length) {
return makeFailure(i, 'any character');
}
return makeSuccess(i + 1, input.charAt(i));
});
MonadicParser.all = new MonadicParser(function (input, i) {
return makeSuccess(input.length, input.slice(i));
});
MonadicParser.eof = new MonadicParser(function (input, i) {
if (i < input.length) {
return makeFailure(i, 'EOF');
}
return makeSuccess(i, null);
});
MonadicParser.digit = regexp(/[0-9]/).desc('a digit');
MonadicParser.digits = regexp(/[0-9]*/).desc('optional digits');
MonadicParser.letter = regexp(/[a-z]/i).desc('a letter');
MonadicParser.letters = regexp(/[a-z]*/i).desc('optional letters');
MonadicParser.optWhitespace = regexp(/\s*/).desc('optional whitespace');
MonadicParser.whitespace = regexp(/\s+/).desc('whitespace');
MonadicParser.cr = string('\r');
MonadicParser.lf = string('\n');
MonadicParser.crlf = string('\r\n');
MonadicParser.newline = alt(MonadicParser.crlf, MonadicParser.lf, MonadicParser.cr).desc('newline');
MonadicParser.end = alt(MonadicParser.newline, MonadicParser.eof);
function of(value) {
return succeed(value);
}
MonadicParser.of = of;
function regex(re) {
return regexp(re);
}
MonadicParser.regex = regex;
})(MonadicParser || (MonadicParser = {}));
function seqPick(idx) {
var parsers = [];
for (var _i = 1; _i < arguments.length; _i++) {
parsers[_i - 1] = arguments[_i];
}
var numParsers = parsers.length;
return new MonadicParser(function (input, index) {
var result;
var picked;
var i = index;
for (var j = 0; j < numParsers; j++) {
result = mergeReplies(parsers[j]._(input, i), result);
if (!result.status) {
return result;
}
if (idx === j)
picked = result.value;
i = result.index;
}
return mergeReplies(makeSuccess(i, picked), result);
});
}
function makeSuccess(index, value) {
return { status: true, index: index, value: value };
}
function makeFailure(index, expected) {
return { status: false, furthest: index, expected: [expected] };
}
function mergeReplies(result, last) {
if (!last || result.status || last.status || result.furthest > last.furthest) {
return result;
}
var expected = result.furthest === last.furthest
? unsafeUnion(result.expected, last.expected)
: last.expected;
return { status: result.status, 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 };
}
function formatExpected(expected) {
if (expected.length === 1) {
return expected[0];
}
return 'one of ' + expected.join(', ');
}
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 ".concat(index.line, " column ").concat(index.column, ", got ").concat(prefix).concat(input.slice(i, i + 12)).concat(suffix);
}
function formatError(input, error) {
return "expected ".concat(formatExpected(error.expected)).concat(formatGot(input, error));
}
function unsafeUnion(xs, ys) {
var xn = xs.length;
var yn = ys.length;
if (xn === 0)
return ys;
else if (yn === 0)
return xs;
var set = new Set();
var ret = [];
for (var i = 0; i < xn; i++) {
if (!set.has(xs[i])) {
ret[ret.length] = xs[i];
set.add(xs[i]);
}
}
for (var i = 0; i < yn; i++) {
if (!set.has(ys[i])) {
ret[ret.length] = ys[i];
set.add(ys[i]);
}
}
ret.sort();
return ret;
}
function isParser(obj) {
return obj instanceof MonadicParser;
}
function assertFunction(x) {
if (typeof x !== 'function') {
throw new Error('not a function: ' + x);
}
}