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.

310 lines
6.5 KiB
JavaScript

"use strict";
const fs = require( "fs" );
const path = require( "path" );
const peg = require( "../lib/peg" );
// Options
let inputFile = null;
let outputFile = null;
const 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( json ) {
let extraOptions;
try {
extraOptions = JSON.parse( json );
} catch ( e ) {
if ( ! ( e instanceof SyntaxError ) ) throw e;
abort( "Error parsing JSON: " + e.message );
}
if ( typeof extraOptions !== "object" ) {
abort( "The JSON with extra options has to represent an object." );
}
Object
.keys( extraOptions )
.forEach( key => {
options[ key ] = extraOptions[ key ];
} );
}
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 json, 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" );
try {
json = fs.readFileSync( argument, "utf8" );
} catch ( e ) {
abort( `Can't read from file "${ argument }".` );
}
addExtraOptions( json );
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;