"use strict"; const Promise = require("bluebird"); const pegRedux = require("peg-redux"); const moduleEval = require("eval"); const vm = require("vm"); const asExpression = require("as-expression"); const { chain } = require("error-chain"); const textParser = require("../text-parser"); const { validateOptions } = require("@validatem/core"); const isString = require("@validatem/is-string"); const isPlainObject = require("@validatem/is-plain-object"); const requireEither = require("@validatem/require-either"); module.exports = function createPegParser(_options) { let { grammar, grammarFile, options } = validateOptions(arguments, [ { grammar: [ isString ], grammarFile: [ isString ], options: [ isPlainObject ] }, requireEither([ "grammar", "grammarFile" ]) ]); let parserOptions = { ... options, output: "source", format: "commonjs" }; return Promise.try(() => { return (grammarFile != null) ? pegRedux.generateFromFile(grammarFile, parserOptions) : pegRedux.generate(grammar, parserOptions); }).then((parserCode) => { let parser = asExpression(() => { if (grammarFile != null) { return moduleEval(parserCode, grammarFile, {}, true); } else { let exports_ = {}; let sandbox = { exports: exports_, module: { exports: exports_, }, require: function () { throw new Error("You cannot use require() when loading a grammar as a string; use the `grammarFile` option instead"); } }; let script = new vm.Script(parserCode.replace(/^\#\!.*/, '')); script.runInNewContext(sandbox); return sandbox.module.exports; } }); return { supportsStreams: false, parse: function (text) { try { return parser.parse(text); } catch (error) { if (error.name === "SyntaxError") { throw chain(error, textParser.NoResult, "Parsing output failed"); } else { throw error; } } } }; }); };