b6bc0d905e
This commit adds support for '.js' files to be passed to the '-c', '--config' or '--extra-options-file' options on the CLI, allowing the developer to do some extra work before the parser is generated (if they wish), or dynamically set options based on the enviroment.
317 lines
6.8 KiB
JavaScript
317 lines
6.8 KiB
JavaScript
"use strict";
|
|
|
|
const fs = require( "fs" );
|
|
const path = require( "path" );
|
|
const peg = require( "../lib/peg" );
|
|
const util = peg.util;
|
|
|
|
// Options
|
|
|
|
let inputFile = null;
|
|
let outputFile = null;
|
|
let options = {
|
|
"--": [],
|
|
"cache": false,
|
|
"dependencies": {},
|
|
"exportVar": null,
|
|
"format": "commonjs",
|
|
"optimize": "speed",
|
|
"output": "source",
|
|
"plugins": [],
|
|
"trace": false
|
|
};
|
|
|
|
const EXPORT_VAR_FORMATS = [ "globals", "umd" ];
|
|
const DEPENDENCY_FORMATS = [ "amd", "commonjs", "es", "umd" ];
|
|
const MODULE_FORMATS = [ "amd", "bare", "commonjs", "es", "globals", "umd" ];
|
|
const OPTIMIZATION_GOALS = [ "size", "speed" ];
|
|
|
|
// Helpers
|
|
|
|
function abort( message ) {
|
|
|
|
console.error( message );
|
|
process.exit( 1 );
|
|
|
|
}
|
|
|
|
function addExtraOptions( config ) {
|
|
|
|
if ( typeof config === "string" ) {
|
|
|
|
try {
|
|
|
|
config = JSON.parse( config );
|
|
|
|
} catch ( e ) {
|
|
|
|
if ( ! ( e instanceof SyntaxError ) ) throw e;
|
|
abort( "Error parsing JSON: " + e.message );
|
|
|
|
}
|
|
|
|
}
|
|
if ( typeof config !== "object" ) {
|
|
|
|
abort( "The JSON with extra options has to represent an object." );
|
|
|
|
}
|
|
|
|
const extraOptions = {};
|
|
util.extend( extraOptions, config );
|
|
util.extend( extraOptions, options );
|
|
options = extraOptions;
|
|
|
|
}
|
|
|
|
function formatChoicesList( list ) {
|
|
|
|
list = list.map( entry => `"${ entry }"` );
|
|
const lastOption = list.pop();
|
|
|
|
return list.length === 0
|
|
? lastOption
|
|
: list.join( ", " ) + " or " + lastOption;
|
|
|
|
}
|
|
|
|
function updateList( list, string ) {
|
|
|
|
string
|
|
.split( "," )
|
|
.forEach( entry => {
|
|
|
|
entry = entry.trim();
|
|
if ( list.indexOf( entry ) === -1 ) {
|
|
|
|
list.push( entry );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
// Arguments
|
|
|
|
let args = process.argv.slice( 2 );
|
|
|
|
function nextArg( option ) {
|
|
|
|
if ( args.length === 0 ) {
|
|
|
|
abort( `Missing parameter of the ${ option } option.` );
|
|
|
|
}
|
|
return args.shift();
|
|
|
|
}
|
|
|
|
// Parse Arguments
|
|
|
|
while ( args.length > 0 ) {
|
|
|
|
let config, mod;
|
|
let argument = args.shift();
|
|
|
|
if ( argument.indexOf( "-" ) === 0 && argument.indexOf( "=" ) > 1 ) {
|
|
|
|
argument = argument.split( "=" );
|
|
args.unshift( argument.length > 2 ? argument.slice( 1 ) : argument[ 1 ] );
|
|
argument = argument[ 0 ];
|
|
|
|
}
|
|
|
|
switch ( argument ) {
|
|
|
|
case "--":
|
|
options[ "--" ] = args;
|
|
args = [];
|
|
break;
|
|
|
|
case "-a":
|
|
case "--allowed-start-rules":
|
|
if ( ! options.allowedStartRules ) options.allowedStartRules = [];
|
|
updateList( options.allowedStartRules, nextArg( "--allowed-start-rules" ) );
|
|
break;
|
|
|
|
case "--cache":
|
|
options.cache = true;
|
|
break;
|
|
|
|
case "--no-cache":
|
|
options.cache = false;
|
|
break;
|
|
|
|
case "-d":
|
|
case "--dependency":
|
|
argument = nextArg( "-d/--dependency" );
|
|
mod = argument.split( ":" );
|
|
|
|
if ( mod.length === 1 ) mod = [ argument, argument ];
|
|
else if ( mod.length > 2 ) mod[ 1 ] = mod.slice( 1 );
|
|
|
|
options.dependencies[ mod[ 0 ] ] = mod[ 1 ];
|
|
break;
|
|
|
|
case "-e":
|
|
case "--export-var":
|
|
options.exportVar = nextArg( "-e/--export-var" );
|
|
break;
|
|
|
|
case "--extra-options":
|
|
addExtraOptions( nextArg( "--extra-options" ) );
|
|
break;
|
|
|
|
case "-c":
|
|
case "--config":
|
|
case "--extra-options-file":
|
|
argument = nextArg( "-c/--config/--extra-options-file" );
|
|
if ( path.extname( argument ) === ".js" ) {
|
|
|
|
config = require( path.resolve( argument ) );
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
config = fs.readFileSync( argument, "utf8" );
|
|
|
|
} catch ( e ) {
|
|
|
|
abort( `Can't read from file "${ argument }".` );
|
|
|
|
}
|
|
|
|
}
|
|
addExtraOptions( config );
|
|
break;
|
|
|
|
case "-f":
|
|
case "--format":
|
|
argument = nextArg( "-f/--format" );
|
|
if ( MODULE_FORMATS.indexOf( argument ) === -1 ) {
|
|
|
|
abort( `Module format must be either ${ formatChoicesList( MODULE_FORMATS ) }.` );
|
|
|
|
}
|
|
options.format = argument;
|
|
break;
|
|
|
|
case "-h":
|
|
case "--help":
|
|
console.log( require( "./usage" ) );
|
|
process.exit();
|
|
break;
|
|
|
|
case "-O":
|
|
case "--optimize":
|
|
argument = nextArg( "-O/--optimize" );
|
|
if ( OPTIMIZATION_GOALS.indexOf( argument ) === -1 ) {
|
|
|
|
abort( `Optimization goal must be either ${ formatChoicesList( OPTIMIZATION_GOALS ) }.` );
|
|
|
|
}
|
|
options.optimize = argument;
|
|
break;
|
|
|
|
case "-o":
|
|
case "--output":
|
|
outputFile = nextArg( "-o/--output" );
|
|
break;
|
|
|
|
case "-p":
|
|
case "--plugin":
|
|
argument = nextArg( "-p/--plugin" );
|
|
try {
|
|
|
|
mod = require( argument );
|
|
|
|
} catch ( ex1 ) {
|
|
|
|
if ( ex1.code !== "MODULE_NOT_FOUND" ) throw ex1;
|
|
try {
|
|
|
|
mod = require( path.resolve( argument ) );
|
|
|
|
} catch ( ex2 ) {
|
|
|
|
if ( ex2.code !== "MODULE_NOT_FOUND" ) throw ex2;
|
|
abort( `Can't load module "${ argument }".` );
|
|
|
|
}
|
|
|
|
}
|
|
options.plugins.push( mod );
|
|
break;
|
|
|
|
case "--trace":
|
|
options.trace = true;
|
|
break;
|
|
|
|
case "--no-trace":
|
|
options.trace = false;
|
|
break;
|
|
|
|
case "-v":
|
|
case "--version":
|
|
console.log( "PEG.js v" + peg.VERSION );
|
|
process.exit();
|
|
break;
|
|
|
|
default:
|
|
if ( inputFile !== null ) {
|
|
|
|
abort( `Unknown option: "${ argument }".` );
|
|
|
|
}
|
|
inputFile = argument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Validation and defaults
|
|
|
|
if ( Object.keys( options.dependencies ).length > 0 ) {
|
|
|
|
if ( DEPENDENCY_FORMATS.indexOf( options.format ) === -1 ) {
|
|
|
|
abort( `Can't use the -d/--dependency option with the "${ options.format }" module format.` );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( options.exportVar !== null ) {
|
|
|
|
if ( EXPORT_VAR_FORMATS.indexOf( options.format ) === -1 ) {
|
|
|
|
abort( `Can't use the -e/--export-var option with the "${ options.format }" module format.` );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( inputFile === null ) inputFile = "-";
|
|
|
|
if ( outputFile === null ) {
|
|
|
|
if ( inputFile === "-" ) outputFile = "-";
|
|
else if ( inputFile ) {
|
|
|
|
outputFile = inputFile
|
|
.substr( 0, inputFile.length - path.extname( inputFile ).length )
|
|
+ ".js";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Export
|
|
|
|
options.inputFile = inputFile;
|
|
options.outputFile = outputFile;
|
|
|
|
module.exports = options;
|