You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
1.9 KiB
JavaScript
75 lines
1.9 KiB
JavaScript
"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;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
});
|
|
};
|