@masala/parser
Version:
256 lines (213 loc) • 7.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.string = string;
var _parser = require('./parser');
var _parser2 = _interopRequireDefault(_parser);
var _response = require('./response');
var _response2 = _interopRequireDefault(_response);
var _tuple = require('../data/tuple');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// (Stream 'c -> number -> Response 'a 'c) -> Parser 'a 'c
function parse(p) {
return new _parser2.default(p);
}
// (('b -> Parser 'a 'c) * 'b)-> Parser 'a 'c
/*
* Parsec
* https://github.com/d-plaindoux/parsec
*
* Copyright (c) 2016 Didier Plaindoux
* Licensed under the LGPL2 license.
*/
function lazy(p, parameters) {
var self = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (parameters && !Array.isArray(parameters)) {
throw 'Lazy(parser, [params]) function expect parser parameters to be packed into an array';
}
// equivalent of p(...parameters), but would fail if parameters are undefined
// In some case, p is a function that require a 'this' bound to the function
// https://github.com/d-plaindoux/masala-parser/issues/9
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return p.apply(self, parameters).parse(input, index);
});
}
// 'a -> Parser 'a 'c
function returns(v) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return _response2.default.accept(v, input, index, false);
});
}
// unit -> Parser 'a 'c
function error() {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
// TODO: add an optional logger parameter, and log
return _response2.default.reject(input, index, false);
});
}
// ('a -> boolean) -> Parser a 'c
// index is forwarded at index +1
function satisfy(predicate) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return input.get(index).filter(predicate).map(function (value) {
return _response2.default.accept(value, input, index + 1, true);
}).lazyRecoverWith(function () {
return _response2.default.reject(input, index, false);
});
});
}
// Parser 'a 'c -> Parser 'a 'c
function doTry(p) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return p.parse(input, index).fold(function (accept) {
return accept;
},
// Compared to satisfy, we come back to initial offset
function (reject) {
return _response2.default.reject(input, reject.offset, false);
});
});
}
function layer(p) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return p.parse(input, index).fold(function (accept) {
// TODO logger
return _response2.default.accept(new _tuple.Tuple().append(accept.value), input, index, false);
},
// Compared to satisfy, we come back to initial offset
function (reject) {
return reject;
});
});
}
// unit -> Parser 'a 'c
function any() {
return satisfy(function () {
return true;
});
}
// unit -> Parser 'a 'c
function nop() {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return _response2.default.accept(_tuple.NEUTRAL, input, index, true);
});
}
// Parser 'a ? -> Parser 'a 'a
function not(p) {
return doTry(p).then(error()).or(any());
}
// int -> Parser (List 'a') a'
function subStream(length) {
return any().occurrence(length);
}
function startWith(value) {
return nop().returns(value);
}
function moveUntil(stop) {
if (typeof stop === 'string') {
return searchStringStart(stop);
}
if (Array.isArray(stop)) {
return searchArrayStringStart(stop);
}
// TODO: change undefined by a Symbol
// TODO: for better performance, maybe check in the map if the symbol is included, and remove the or
var foundEos = Symbol('found-eos');
return doTry(not(stop).rep().then((0, _parser.eos)()).returns(foundEos)).or(not(stop).rep().map(function (chars) {
return chars.join('');
})).filter(function (v) {
return v !== foundEos;
});
}
function dropTo(stop) {
if (typeof stop === 'string') {
return moveUntil(stop).then(string(stop)).drop();
} else {
return moveUntil(stop).then(stop).drop();
}
}
exports.default = {
parse: parse,
nop: nop,
try: doTry,
any: any,
subStream: subStream,
not: not,
layer: layer,
lazy: lazy,
returns: returns,
error: error,
eos: _parser.eos,
satisfy: satisfy,
startWith: startWith,
moveUntil: moveUntil,
dropTo: dropTo
};
/**Optimization functions */
/**
* Will work only if input.source is a String
* @param string
* @returns {Parser}
*/
function searchStringStart(string) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (typeof input.source !== 'string') {
throw 'Input source must be a String';
}
var sourceIndex = input.source.indexOf(string, index);
if (sourceIndex > 0) {
return _response2.default.accept(input.source.substring(index, sourceIndex), input, sourceIndex, true);
} else {
return _response2.default.reject(input, index, false);
}
});
}
/**
* Will work only if input.source is a String
*/
function searchArrayStringStart(array) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (typeof input.source !== 'string') {
throw 'Input source must be a String';
}
var sourceIndex = -1;
var i = 0;
while (sourceIndex < 0 && i < array.length) {
var needle = array[i];
sourceIndex = input.source.indexOf(needle, index);
i++;
if (sourceIndex > 0) {
break;
}
}
//const sourceIndex = input.source.indexOf(string, index)
if (sourceIndex > 0) {
return _response2.default.accept(input.source.substring(index, sourceIndex), input, sourceIndex, true);
} else {
return _response2.default.reject(input, index, false);
}
});
}
// string -> Parser string char
// index is forwarded at the length of the string
function string(s) {
return new _parser2.default(function (input) {
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (input.subStreamAt(s.split(''), index)) {
return _response2.default.accept(s, input, index + s.length, true);
} else {
return _response2.default.reject(input, index, false);
}
});
}
//# sourceMappingURL=flow-bundle.js.map