jison-es
Version:
Fork of jison that emits parsers as ES modules
188 lines (164 loc) • 5 kB
JavaScript
function getCommandlineOptions () {
"use strict";
var version = require('../package.json').version;
var opts = require("nomnom")
.script('jison')
.option('file', {
flag : true,
position : 0,
help : 'file containing a grammar'
})
.option('lexfile', {
flag : true,
position : 1,
help : 'file containing a lexical grammar'
})
.option('json', {
abbr : 'j',
flag : true,
help : 'force jison to expect a grammar in JSON format'
})
.option('outfile', {
abbr : 'o',
metavar : 'FILE',
help : 'Filename and base module name of the generated parser'
})
.option('debug', {
abbr : 't',
flag : true,
default:
false,
help : 'Debug mode'
})
.option('module-type', {
abbr : 'm',
default:
'es',
metavar : 'TYPE',
help : 'The type of module to generate (es, commonjs, amd, js)'
})
.option('parser-type', {
abbr : 'p',
default:
'lalr',
metavar : 'TYPE',
help : 'The type of algorithm to use for the parser (lr0, slr,' +
'lalr, lr)'
})
.option('version', {
abbr : 'V',
flag : true,
help : 'print version and exit',
callback : function () {
return version;
}
}).parse();
return opts;
}
var cli = module.exports;
cli.main = function cliMain(opts) {
"use strict";
opts = opts || {};
function processGrammar(raw, lex, opts) {
var grammar,
parser;
grammar = cli.processGrammars(raw, lex, opts.json);
parser = cli.generateParserString(opts, grammar);
return parser;
}
function processInputFile () {
var fs = require('fs');
var path = require('path');
// getting raw files
var lex;
if (opts.lexfile) {
lex = fs.readFileSync(path.normalize(opts.lexfile), 'utf8');
}
var raw = fs.readFileSync(path.normalize(opts.file), 'utf8');
// making best guess at json mode
opts.json = path.extname(opts.file) === '.json' || opts.json;
// setting output file name and module name based on input file name
// if they aren't specified.
var name = path.basename((opts.outfile || opts.file));
name = name.replace(/\..*$/g, '');
opts.outfile = opts.outfile || (name + '.js');
if (!opts.moduleName && name) {
opts.moduleName = name.replace(/-\w/g,
function (match) {
return match.charAt(1).toUpperCase();
});
}
var parser = processGrammar(raw, lex, opts);
fs.writeFileSync(opts.outfile, parser);
}
function readin(cb) {
var stdin = process.openStdin(),
data = '';
stdin.setEncoding('utf8');
stdin.addListener('data', function (chunk) {
data += chunk;
});
stdin.addListener('end', function () {
cb(data);
});
}
function processStdin () {
readin(function (raw) {
console.log(processGrammar(raw, null, opts));
});
}
// if an input file wasn't given, assume input on stdin
if (opts.file) {
processInputFile();
} else {
processStdin();
}
};
cli.generateParserString = function generateParserString(opts, grammar) {
"use strict";
opts = opts || {};
var jison = require('./jison.js');
var settings = grammar.options || {};
if (opts['parser-type']) {
settings.type = opts['parser-type'];
}
if (opts.moduleName) {
settings.moduleName = opts.moduleName;
}
settings.debug = opts.debug;
if (!settings.moduleType) {
settings.moduleType = opts['module-type'];
}
var generator = new jison.Generator(grammar, settings);
return generator.generate(settings);
};
cli.processGrammars = function processGrammars(file, lexFile, jsonMode) {
"use strict";
lexFile = lexFile || false;
jsonMode = jsonMode || false;
var ebnfParser = require('ebnf-parser');
var cjson = require('cjson');
var grammar;
try {
if (jsonMode) {
grammar = cjson.parse(file);
} else {
grammar = ebnfParser.parse(file);
}
} catch (e) {
throw new Error('Could not parse jison grammar');
}
try {
if (lexFile) {
grammar.lex = require('lex-parser').parse(lexFile);
}
} catch (e) {
throw new Error('Could not parse lex grammar');
}
return grammar;
};
if (require.main === module) {
var opts = getCommandlineOptions();
cli.main(opts);
}