2015-06-08 20:21:19 +02:00
|
|
|
"use strict";
|
|
|
|
|
2016-09-14 11:09:53 +02:00
|
|
|
function processOptions(options, defaults) {
|
|
|
|
let processedOptions = {};
|
|
|
|
|
|
|
|
Object.keys(options).forEach(name => {
|
|
|
|
processedOptions[name] = options[name];
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.keys(defaults).forEach(name => {
|
|
|
|
if (!processedOptions.hasOwnProperty(name)) {
|
|
|
|
processedOptions[name] = defaults[name];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return processedOptions;
|
|
|
|
}
|
2012-11-10 09:47:22 +01:00
|
|
|
|
2016-09-08 16:04:36 +02:00
|
|
|
let compiler = {
|
2016-09-17 16:28:28 +02:00
|
|
|
// AST node visitor builder. Useful mainly for plugins which manipulate the
|
|
|
|
// AST.
|
2016-06-20 08:06:14 +02:00
|
|
|
visitor: require("./visitor"),
|
2015-12-11 14:07:44 +01:00
|
|
|
|
2016-09-17 16:28:28 +02:00
|
|
|
// Compiler passes.
|
|
|
|
//
|
|
|
|
// Each pass is a function that is passed the AST. It can perform checks on it
|
|
|
|
// or modify it as needed. If the pass encounters a semantic error, it throws
|
|
|
|
// |peg.GrammarError|.
|
2013-01-06 20:27:35 +01:00
|
|
|
passes: {
|
2013-01-13 11:17:44 +01:00
|
|
|
check: {
|
2016-09-22 05:25:09 +02:00
|
|
|
reportUndefinedRules: require("./passes/report-undefined-rules"),
|
|
|
|
reportDuplicateRules: require("./passes/report-duplicate-rules"),
|
|
|
|
reportDuplicateLabels: require("./passes/report-duplicate-labels"),
|
|
|
|
reportInfiniteRecursion: require("./passes/report-infinite-recursion"),
|
2016-07-29 18:06:16 +02:00
|
|
|
reportInfiniteRepetition: require("./passes/report-infinite-repetition")
|
2013-01-13 11:17:44 +01:00
|
|
|
},
|
|
|
|
transform: {
|
2016-09-22 05:25:09 +02:00
|
|
|
removeProxyRules: require("./passes/remove-proxy-rules")
|
2013-01-13 11:17:44 +01:00
|
|
|
},
|
|
|
|
generate: {
|
2016-09-22 05:25:09 +02:00
|
|
|
generateBytecode: require("./passes/generate-bytecode"),
|
|
|
|
generateJS: require("./passes/generate-js")
|
2013-01-13 11:17:44 +01:00
|
|
|
}
|
2013-01-06 20:27:35 +01:00
|
|
|
},
|
2012-11-10 09:47:22 +01:00
|
|
|
|
2016-09-17 16:28:28 +02:00
|
|
|
// Generates a parser from a specified grammar AST. Throws |peg.GrammarError|
|
|
|
|
// if the AST contains a semantic error. Note that not all errors are detected
|
|
|
|
// during the generation and some may protrude to the generated parser and
|
|
|
|
// cause its malfunction.
|
2016-03-18 16:39:19 +01:00
|
|
|
compile: function(ast, passes, options) {
|
2016-09-01 14:12:16 +02:00
|
|
|
options = options !== undefined ? options : {};
|
2013-01-13 11:17:44 +01:00
|
|
|
|
2016-09-14 11:09:53 +02:00
|
|
|
options = processOptions(options, {
|
2016-04-28 10:10:48 +02:00
|
|
|
allowedStartRules: [ast.rules[0].name],
|
2016-09-22 05:25:09 +02:00
|
|
|
cache: false,
|
|
|
|
dependencies: {},
|
|
|
|
exportVar: null,
|
|
|
|
format: "bare",
|
|
|
|
optimize: "speed",
|
|
|
|
output: "parser",
|
|
|
|
trace: false
|
2013-01-06 10:32:52 +01:00
|
|
|
});
|
2011-10-03 14:14:14 +02:00
|
|
|
|
2016-09-14 16:08:14 +02:00
|
|
|
Object.keys(passes).forEach(stage => {
|
|
|
|
passes[stage].forEach(p => { p(ast, options); });
|
|
|
|
});
|
2010-07-25 17:54:09 +02:00
|
|
|
|
2013-01-06 10:32:52 +01:00
|
|
|
switch (options.output) {
|
2012-11-11 18:18:52 +01:00
|
|
|
case "parser": return eval(ast.code);
|
|
|
|
case "source": return ast.code;
|
|
|
|
}
|
2010-07-25 17:54:09 +02:00
|
|
|
}
|
|
|
|
};
|
2014-05-04 14:11:44 +02:00
|
|
|
|
|
|
|
module.exports = compiler;
|