|
|
|
var utils = require("./utils");
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
/*
|
|
|
|
* 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|.
|
|
|
|
*/
|
|
|
|
passes: {
|
|
|
|
check: {
|
|
|
|
reportMissingRules: require("./compiler/passes/report-missing-rules"),
|
|
|
|
reportLeftRecursion: require("./compiler/passes/report-left-recursion")
|
|
|
|
},
|
|
|
|
transform: {
|
|
|
|
removeProxyRules: require("./compiler/passes/remove-proxy-rules")
|
|
|
|
},
|
|
|
|
generate: {
|
|
|
|
generateBytecode: require("./compiler/passes/generate-bytecode"),
|
|
|
|
generateJavascript: require("./compiler/passes/generate-javascript")
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
compile: function(ast, passes) {
|
|
|
|
var options = arguments.length > 2 ? utils.clone(arguments[2]) : {},
|
|
|
|
stage;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extracted into a function just to silence JSHint complaining about
|
|
|
|
* creating functions in a loop.
|
|
|
|
*/
|
|
|
|
function runPass(pass) {
|
|
|
|
pass(ast, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
utils.defaults(options, {
|
|
|
|
allowedStartRules: [ast.rules[0].name],
|
|
|
|
cache: false,
|
|
|
|
optimize: "speed",
|
|
|
|
output: "parser"
|
|
|
|
});
|
|
|
|
|
|
|
|
for (stage in passes) {
|
|
|
|
utils.each(passes[stage], runPass);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (options.output) {
|
|
|
|
case "parser": return eval(ast.code);
|
|
|
|
case "source": return ast.code;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|