pegjs/lib/compiler/index.js
Mingun 42ec335d13 Optimize silent fails: remove checks that always false (#399)
* Optimization: do not generate unreachable calls |peg$fail| and constants for it (local to the rule).
* Optimization: do not generate unreachable calls |peg$fail| and constants for it (non-local to rule).
2018-01-01 19:35:59 +00:00

112 lines
3.2 KiB
JavaScript

"use strict";
const calcReportFailures = require( "./passes/calc-report-failures" );
const generateBytecode = require( "./passes/generate-bytecode" );
const generateJS = require( "./passes/generate-js" );
const removeProxyRules = require( "./passes/remove-proxy-rules" );
const reportDuplicateLabels = require( "./passes/report-duplicate-labels" );
const reportDuplicateRules = require( "./passes/report-duplicate-rules" );
const reportInfiniteRecursion = require( "./passes/report-infinite-recursion" );
const reportInfiniteRepetition = require( "./passes/report-infinite-repetition" );
const reportUndefinedRules = require( "./passes/report-undefined-rules" );
const visitor = require( "./visitor" );
function processOptions( options, defaults ) {
const processedOptions = {};
Object.keys( options ).forEach( name => {
processedOptions[ name ] = options[ name ];
} );
Object.keys( defaults ).forEach( name => {
if ( ! Object.prototype.hasOwnProperty.call( processedOptions, name ) ) {
processedOptions[ name ] = defaults[ name ];
}
} );
return processedOptions;
}
const compiler = {
// AST node visitor builder. Useful mainly for plugins which manipulate the
// AST.
visitor: visitor,
// 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: {
reportUndefinedRules: reportUndefinedRules,
reportDuplicateRules: reportDuplicateRules,
reportDuplicateLabels: reportDuplicateLabels,
reportInfiniteRecursion: reportInfiniteRecursion,
reportInfiniteRepetition: reportInfiniteRepetition
},
transform: {
removeProxyRules: removeProxyRules
},
generate: {
calcReportFailures: calcReportFailures,
generateBytecode: generateBytecode,
generateJS: generateJS
}
},
// 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( ast, passes, options ) {
options = typeof options !== "undefined" ? options : {};
options = processOptions( options, {
allowedStartRules: [ ast.rules[ 0 ].name ],
cache: false,
dependencies: {},
exportVar: null,
format: "bare",
optimize: "speed",
output: "parser",
trace: false
} );
Object.keys( passes ).forEach( stage => {
passes[ stage ].forEach( pass => {
pass( ast, options );
} );
} );
switch ( options.output ) {
case "parser":
return eval( ast.code );
case "source":
return ast.code;
default:
throw new Error( `Invalid output format: ${ options.output }.` );
}
}
};
module.exports = compiler;