This repository was archived by the owner on Jun 15, 2019. It is now read-only.
forked from zaach/jison-lex
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcli.js
executable file
·235 lines (202 loc) · 7.9 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import fs from 'fs';
import path from 'path';
import nomnom from '@gerhobbelt/nomnom';
import RegExpLexer from './regexp-lexer.js';
var version = '0.6.1-208'; // require('./package.json').version;
function getCommandlineOptions() {
'use strict';
var opts = nomnom
.script('jison-lex')
.unknownOptionTreatment(false) // do not accept unknown options!
.options({
file: {
flag: true,
position: 0,
help: 'file containing a lexical grammar'
},
json: {
abbr: 'j',
flag: true,
default: false,
help: 'jison will expect a grammar in either JSON/JSON5 or JISON format: the precise format is autodetected'
},
outfile: {
abbr: 'o',
metavar: 'FILE',
help : 'Filepath and base module name of the generated parser;\nwhen terminated with a / (dir separator) it is treated as the destination directory where the generated output will be stored'
},
debug: {
abbr: 'd',
flag: true,
default: false,
help: 'Debug mode'
},
dumpSourceCodeOnFailure: {
full: 'dump-sourcecode-on-failure',
flag: true,
default: true,
help: 'Dump the generated source code to a special named file when the internal generator tests fail, i.e. when the generated source code does not compile in the JavaScript engine. Enabling this option helps you to diagnose/debug crashes (thrown exceptions) in the code generator due to various reasons: you can, for example, load the dumped sourcecode in another environment (e.g. NodeJS) to get more info on the precise location and cause of the compile failure.'
},
throwErrorOnCompileFailure: {
full: 'throw-on-compile-failure',
flag: true,
default: true,
help: 'Throw an exception when the generated source code fails to compile in the JavaScript engine. **WARNING**: Turning this feature OFF permits the code generator to produce non-working source code and treat that as SUCCESS. This MAY be desirable code generator behaviour, but only rarely.'
},
reportStats: {
full: 'info',
abbr: 'I',
flag: true,
default: false,
help: 'Report some statistics about the generated parser'
},
moduleType: {
full: 'module-type',
abbr: 't',
default: 'commonjs',
metavar: 'TYPE',
choices: ['commonjs', 'amd', 'js', 'es'],
help: 'The type of module to generate (commonjs, amd, es, js)'
},
moduleName: {
full: 'module-name',
abbr: 'n',
metavar: 'NAME',
help: 'The name of the generated parser object, namespace supported'
},
main: {
full: 'main',
abbr: 'x',
flag: true,
default: false,
help: 'Include .main() entry point in generated commonjs module'
},
moduleMain: {
full: 'module-main',
abbr: 'y',
metavar: 'NAME',
help: 'The main module function definition'
},
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 = RegExpLexer.mkStdOptions(opts);
function isDirectory(fp) {
try {
return fs.lstatSync(fp).isDirectory();
} catch (e) {
return false;
}
}
function mkdirp(fp) {
if (!fp || fp === '.' || fp.length === 0) {
return false;
}
try {
fs.mkdirSync(fp);
return true;
} catch (e) {
if (e.code === 'ENOENT') {
var parent = path.dirname(fp);
// Did we hit the root directory by now? If so, abort!
// Else, create the parent; iff that fails, we fail too...
if (parent !== fp && mkdirp(parent)) {
try {
// Retry creating the original directory: it should succeed now
fs.mkdirSync(fp);
return true;
} catch (e) {
return false;
}
}
}
}
return false;
}
function processInputFile() {
// getting raw files
var lex;
var original_cwd = process.cwd();
var raw = fs.readFileSync(path.normalize(opts.file), 'utf8');
// making best guess at json mode
opts.json = path.extname(opts.file) === '.json' || opts.json;
// When only the directory part of the output path was specified, then we
// do NOT have the target module name in there as well!
var outpath = opts.outfile;
if (/[\\\/]$/.test(outpath) || isDirectory(outpath)) {
opts.outfile = null;
outpath = outpath.replace(/[\\\/]$/, '');
}
if (outpath && outpath.length > 0) {
outpath += '/';
} else {
outpath = '';
}
// 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);
// get the base name (i.e. the file name without extension)
// i.e. strip off only the extension and keep any other dots in the filename
name = path.basename(name, path.extname(name));
opts.outfile = opts.outfile || (outpath + name + '.js');
if (!opts.moduleName && name) {
opts.moduleName = opts.defaultModuleName = name.replace(/-\w/g,
function (match) {
return match.charAt(1).toUpperCase();
});
}
// Change CWD to the directory where the source grammar resides: this helps us properly
// %include any files mentioned in the grammar with relative paths:
var new_cwd = path.dirname(path.normalize(opts.file));
process.chdir(new_cwd);
var lexer = cli.generateLexerString(raw, opts);
// and change back to the CWD we started out with:
process.chdir(original_cwd);
mkdirp(path.dirname(opts.outfile));
fs.writeFileSync(opts.outfile, lexer);
console.log('JISON-LEX output for module [' + opts.moduleName + '] has been written to file:', opts.outfile);
}
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 processStdinReadInCallback(raw) {
console.log(cli.generateLexerString(raw, opts));
});
}
// if an input file wasn't given, assume input on stdin
if (opts.file) {
processInputFile();
} else {
processStdin();
}
};
cli.generateLexerString = function generateLexerString(lexerSpec, opts) {
'use strict';
// var settings = RegExpLexer.mkStdOptions(opts);
var predefined_tokens = null;
return RegExpLexer.generate(lexerSpec, predefined_tokens, opts);
};
if (require.main === module) {
var opts = getCommandlineOptions();
cli.main(opts);
}