UNPKG

parser-combinator

Version:
315 lines (251 loc) 12.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* * Parsec * https://github.com/d-plaindoux/parsec * * Copyright (c) 2016 Didier Plaindoux * Licensed under the LGPL2 license. */ /* * Parsec: Direct Style Monadic Parser Combinators For The Real World * * http://research.microsoft.com/en-us/um/people/daan/download/papers/parsec-paper.pdf */ var _index = require('../stream/index'); var _index2 = _interopRequireDefault(_index); var _option = require('../data/option'); var _option2 = _interopRequireDefault(_option); var _list = require('../data/list'); var _list2 = _interopRequireDefault(_list); var _response = require('./response'); var _response2 = _interopRequireDefault(_response); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Parser class */ var Parser = function () { // (Stream 'c -> number -> Response 'a 'c) -> Parser 'a 'c function Parser(parse) { _classCallCheck(this, Parser); this.parse = parse; } // Parser 'a 'c => ('a -> Parser 'b 'c) -> Parser 'b 'c _createClass(Parser, [{ key: 'flatmap', value: function flatmap(f) { return bind(this, f); } // Parser 'a 'c => ('a -> 'b) -> Parser 'b 'c }, { key: 'map', value: function map(f) { var self = this; return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return self.parse(input, index).map(f); }); } // Parser 'a 'c => ('a -> boolean) -> Parser 'a 'c }, { key: 'filter', value: function filter(p) { var self = this; return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return self.parse(input, index).filter(p); }); } // Parser 'a 'c => Comparable 'a -> Parser 'a 'c }, { key: 'match', value: function match(v) { return this.filter(function (a) { return a === v; }); } // Parser 'a 'c => Parser 'b 'c -> Parser ('a,'b) 'c }, { key: 'then', value: function then(p) { return this.flatmap(function (a) { return p.map(function (b) { var result = (0, _list2.default)(a).append((0, _list2.default)(b)).array(); if (result.length == 1) { return result[0]; } else { return result; } }); }); } }, { key: 'concat', value: function concat(p) { return this.then(p); } }, { key: 'drop', value: function drop() { return this.map(function (item) { return []; }); } // Parser 'a 'c => Parser 'b 'c -> Parser 'a 'c }, { key: 'thenLeft', value: function thenLeft(p) { return this.then(p.drop()); } // Parser 'a 'c => Parser 'b 'c -> Parser 'b 'c }, { key: 'thenRight', value: function thenRight(p) { return this.drop().then(p); } // Parser 'a 'c => 'b -> Parser 'b 'c }, { key: 'thenReturns', value: function thenReturns(v) { return this.thenRight(returns(v)); } // Parser 'a 'c -> Parser 'a 'c }, { key: 'or', value: function or(p) { return choice(this, p); } // Parser 'a 'c => unit -> Parser (Option 'a) 'c }, { key: 'opt', value: function opt() { return this.map(_option2.default.some).or(returns(_option2.default.none())); } // Parser 'a 'c => unit -> Parser (List 'a) 'c }, { key: 'rep', value: function rep() { return repeatable(this, function () { return true; }, function (l) { return l !== 0; }); } // Parser 'a 'c => number -> Parser (List 'a) 'c }, { key: 'occurrence', value: function occurrence(_occurrence) { return repeatable(this, function (l) { return l < _occurrence; }, function (l) { return l === _occurrence; }); } // Parser 'a 'c => unit -> Parser (List 'a) 'c }, { key: 'optrep', value: function optrep() { return repeatable(this, function () { return true; }, function () { return true; }); } // Parser 'a 'c => Parser 'b 'a -> Parser 'b 'c }, { key: 'chain', value: function chain(p) { var self = this; return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return p.parse(_index2.default.buffered(_index2.default.ofParser(self, input)), index); }); } /** * Prints a hint if the parser enters in this step * @param hint * @returns the equivalent Parser */ }, { key: 'debug', value: function debug(hint) { var details = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var f = function f(p) { if (details) { console.log('[debug] : ', hint, p); } else { console.log('[debug] : ', hint); } return p; }; return this.map(f); } }]); return Parser; }(); // Response 'a 'c -> ('a -> Parser 'b 'c) -> Response 'b 'c exports.default = Parser; function bindAccepted(accept_a, f) { return f(accept_a.value).parse(accept_a.input, accept_a.offset).fold(function (accept_b) { return _response2.default.accept(accept_b.value, accept_b.input, accept_b.offset, accept_a.consumed || accept_b.consumed); }, function (reject_b) { return _response2.default.reject(accept_a.input.location(reject_b.offset), accept_a.consumed || reject_b.consumed); }); } // Parser 'a 'c -> ('a -> Parser 'b 'c) -> Parser 'b 'c function bind(self, f) { return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return self.parse(input, index).fold(function (accept_a) { return bindAccepted(accept_a, f); }, function (reject_a) { return reject_a; }); }); } // Parser 'a 'c -> Parser 'a 'c -> Parser 'a 'c function choice(self, f) { return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return self.parse(input, index).fold(function (accept) { return accept; }, function (reject) { return reject.consumed ? reject : f.parse(input, index); }); }); } // Parser 'a 'c -> unit -> Parser (List 'a) 'c function repeatable(self, occurrences, accept) { return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var consumed = false, value = (0, _list2.default)(), offset = index, current = self.parse(input, index), occurrence = 0; while (current.isAccepted() && occurrences(occurrence)) { occurrence += 1; value = value.append((0, _list2.default)(current.value)); consumed = consumed || current.consumed; offset = current.offset; current = self.parse(input, current.offset); } if (accept(occurrence)) { return _response2.default.accept(value, input, offset, consumed); } return _response2.default.reject(offset, consumed); }); } /* * Builders */ function returns(v) { return new Parser(function (input) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return _response2.default.accept(v, input, index, false); }); } //# sourceMappingURL=parser.js.map