"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
exports.eos = eos;
var _index = _interopRequireDefault(require("../stream/index.js"));
var _option = _interopRequireDefault(require("../data/option.js"));
var _response = _interopRequireDefault(require("./response.js"));
var _unit = _interopRequireDefault(require("../data/unit.js"));
var _tuple = require("../data/tuple.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*
 * Masala Parser
 * https://github.com/masala/masala-parser
 *
 * Copyright (c) 2016-2025 Didier Plaindoux & Nicolas Zozol
 * 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
 */
/**
 * Parser class
 */
var Parser = exports["default"] = /*#__PURE__*/function () {
  // (Stream 'c -> number -> Response 'a 'c) -> Parser 'a 'c
  function Parser(parse) {
    _classCallCheck(this, Parser);
    this.parse = parse.bind(this);
  }
  return _createClass(Parser, [{
    key: "val",
    value: function val(text) {
      return this.parse(_index["default"].ofString(text)).value;
    }

    // Parser 'a 'c => ('a -> Parser 'b 'c) -> Parser 'b 'c
  }, {
    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
    // 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) {
          return new _tuple.Tuple([]).append(a).append(b);
        });
      });
    }
  }, {
    key: "single",
    value: function single() {
      return this.map(function (tuple) {
        return tuple.single();
      });
    }
  }, {
    key: "last",
    value: function last() {
      return this.map(function (tuple) {
        return tuple.last();
      });
    }
  }, {
    key: "first",
    value: function first() {
      return this.map(function (tuple) {
        return tuple.first();
      });
    }

    // Should be called only on ListParser ; Always returns an array
  }, {
    key: "array",
    value: function array() {
      return this.map(function (value) {
        if (!(0, _tuple.isTuple)(value)) {
          throw 'array() is called only on TupleParser';
        }
        return value.array();
      });
    }
  }, {
    key: "thenEos",
    value: function thenEos() {
      return this.then(eos().drop());
    }
  }, {
    key: "eos",
    value: function eos() {
      var _this = this;
      return new Parser(function (input) {
        var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
        return _this.parse(input, index).fold(function (accept) {
          return input.endOfStream(accept.offset) ? _response["default"].accept(accept.value, accept.input, accept.offset, true) : _response["default"].reject(accept.input, accept.offset, accept.consumed);
        }, function (reject) {
          return _response["default"].reject(reject.input, reject.offset, reject.consumed);
        });
      });
    }
  }, {
    key: "concat",
    value: function concat(p) {
      return this.then(p);
    }
  }, {
    key: "drop",
    value: function drop() {
      return this.map(function () {
        return _tuple.NEUTRAL;
      });
    }

    // 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: "returns",
    value: function returns(v) {
      return this.drop().map(function () {
        return v;
      });
    }

    // Parser 'a 'c -> Parser 'a 'c
  }, {
    key: "or",
    value: function or(p) {
      return choice(this, p);
    }

    /**
     * Must be used with F.layer()
     * @param p
     * @returns {Parser}
     */
  }, {
    key: "and",
    value: function and(p) {
      return both(this, p);
    }

    // Parser 'a 'c => unit -> Parser (Option 'a) 'c
  }, {
    key: "opt",
    value: function opt() {
      return this.map(_option["default"].some).or(returns(_option["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(_index["default"].buffered(_index["default"].ofParser(self, input)), index);
      });
    }

    /**
     * Prints a hint if the parser enters in this step
     * @param hint
     * @param details
     * @returns the equivalent Parser
     */
    // TODO: set details default at false; check tests
  }, {
    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);
    }
  }]);
}(); // Response 'a 'c -> ('a -> Parser 'b 'c) -> Response 'b 'c
function bindAccepted(accept_a, f) {
  return f(accept_a.value).parse(accept_a.input, accept_a.offset).fold(function (accept_b) {
    return _response["default"].accept(accept_b.value, accept_b.input, accept_b.offset, accept_a.consumed || accept_b.consumed);
  }, function (reject_b) {
    return _response["default"].reject(reject_b.input, 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
// TODO logger representing which choice is made
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 -> Parser 'a 'c -> Parser 'a 'c
function both(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 f.parse(input, index).map(function (r) {
        return accept.value.append(r);
      });
    }, function (reject) {
      return reject;
    });
  });
}

// 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 = new _tuple.Tuple([]),
      offset = index,
      current = self.parse(input, index),
      occurrence = 0;
    while (current.isAccepted() && occurrences(occurrence)) {
      occurrence += 1;
      value = value.append(current.value);
      consumed = consumed || current.consumed;
      offset = current.offset;
      current = self.parse(input, current.offset);
    }
    if (accept(occurrence)) {
      return _response["default"].accept(value, input, offset, consumed);
    }
    return _response["default"].reject(input, offset, consumed);
  });
}

/*
 * Builders
 */

function returns(v) {
  return new Parser(function (input) {
    var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    return _response["default"].accept(v, input, index, false);
  });
}

// unit -> Parser unit 'c
function eos() {
  return new Parser(function (input) {
    var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    if (input.endOfStream(index)) {
      return _response["default"].accept(_unit["default"], input, index, false);
    } else {
      return _response["default"].reject(input, index, false);
    }
  });
}
//# sourceMappingURL=parser.js.map