1
1
#!/usr/bin/env node
2
+ /*jslint
3
+ white: true,
4
+ vars: true,
5
+ stupid: true,
6
+ node: true
7
+ */
2
8
3
- var jison = require ( './jison.js' ) ;
4
- var nomnom = require ( 'nomnom' ) ;
5
- var fs = require ( 'fs' ) ;
6
- var path = require ( 'path' ) ;
7
- var ebnfParser = require ( 'ebnf-parser' ) ;
8
- var lexParser = require ( 'lex-parser' ) ;
9
- var cjson = require ( 'cjson' ) ;
9
+ /**
10
+ * jison's cli
11
+ * @fileoverview The cli for jison
12
+ */
10
13
11
- var version = require ( '../package.json' ) . version ;
12
-
13
- var opts = require ( "nomnom" )
14
- . script ( 'jison' )
15
- . option ( 'file' , {
16
- flag : true ,
17
- position : 0 ,
18
- help : 'file containing a grammar'
19
- } )
20
- . option ( 'lexfile' , {
21
- flag : true ,
22
- position : 1 ,
23
- help : 'file containing a lexical grammar'
24
- } )
25
- . option ( 'json' , {
26
- abbr : 'j' ,
27
- flag : true ,
28
- help : 'force jison to expect a grammar in JSON format'
29
- } )
30
- . option ( 'outfile' , {
31
- abbr : 'o' ,
32
- metavar : 'FILE' ,
33
- help : 'Filename and base module name of the generated parser'
34
- } )
35
- . option ( 'debug' , {
36
- abbr : 't' ,
37
- flag : true ,
38
- default : false ,
39
- help : 'Debug mode'
40
- } )
41
- . option ( 'module-type' , {
42
- abbr : 'm' ,
43
- default : 'commonjs' ,
44
- metavar : 'TYPE' ,
45
- help : 'The type of module to generate (commonjs, amd, js)'
46
- } )
47
- . option ( 'parser-type' , {
48
- abbr : 'p' ,
49
- default : 'lalr' ,
50
- metavar : 'TYPE' ,
51
- help : 'The type of algorithm to use for the parser (lr0, slr, lalr, lr)'
52
- } )
53
- . option ( 'version' , {
54
- abbr : 'V' ,
55
- flag : true ,
56
- help : 'print version and exit' ,
57
- callback : function ( ) {
58
- return version ;
14
+ /**
15
+ * Container for cli related functions.
16
+ * @namespace Container for cli related functions.
17
+ */
18
+ var cli = exports ;
19
+ /**
20
+ * Generates a parser and writes it to a file.
21
+ * @param {Object } opts Options object.
22
+ *
23
+ * Options:
24
+ * file: {String} Optional. Path to a file containing a grammar. If no file is
25
+ * specified input will be read from stdin.
26
+ *
27
+ * lexfile: {String} Optional. Path to a file containing a lexical grammar.
28
+ *
29
+ * json: {Boolean} Optional. Set to true if `file` is in json format.
30
+ *
31
+ * outfile: {String} Optional. The path and filename where the parser should be
32
+ * written to. Defaults to the path and filename given for `file` with the file
33
+ * extension replaced by `js`.
34
+ *
35
+ * debug: {Boolean} Optional. Debug mode. Defaults to false.
36
+ *
37
+ * module-type: {String} Optional. The module type of the generated parser.
38
+ * Options are: commonjs, amd, and js. Defaults to commonjs.
39
+ *
40
+ * parser-type: {String} Optional. The type of parser to generate. Options are:
41
+ * lr0, slr, lalr, and lr. Defaults to lalr.
42
+ *
43
+ * @example
44
+ * // grammar to process is not json and contains grammars for lexer and
45
+ * // parser.
46
+ * var jisonCli = require('./node_modules/jison/lib/cli.js');
47
+ * var options = {
48
+ * file : "myfile.jison",
49
+ * moduleName : "myModule"
50
+ * };
51
+ * jisonCli.main(options);
52
+ * @example
53
+ * // grammar to process is not json and is divided into two files containing
54
+ * // the grammars for the lexer and parser seperately.
55
+ * var jisonCli = require('./node_modules/jison/lib/cli.js');
56
+ * var options = {
57
+ * file : "myfile.y",
58
+ * lexfile : "myfile.l",
59
+ * moduleName : "myModule"
60
+ * };
61
+ * jisonCli.main(options);
62
+ * @example
63
+ * // grammar to process is in json format, desired module type is amd, and
64
+ * // desired parser type is lr0.
65
+ * var jisonCli = require('./node_modules/jison/lib/cli.js');
66
+ * var options = {
67
+ * file : "myfile.json",
68
+ * moduleName : "myModule",
69
+ * json : true,
70
+ * "module-type" : "amd",
71
+ * "parser-type" : "lr0"
72
+ * };
73
+ * jisonCli.main(options);
74
+ */
75
+ cli . main = function cli_main ( opts ) {
76
+ "use strict" ;
77
+ opts = opts || { } ;
78
+ /**
79
+ * Generates a parser as a string.
80
+ * @private
81
+ */
82
+ function processGrammar ( raw , lex , opts ) {
83
+ var grammar ,
84
+ parser ;
85
+ if ( ! opts . json ) {
86
+ grammar = cli . processGrammars ( raw , lex , opts . json ) ;
87
+ }
88
+ parser = cli . generateParserString ( opts , grammar ) ;
89
+ return parser ;
59
90
}
60
- } )
61
- . parse ( ) ;
62
-
91
+ /**
92
+ * Processes input from a file.
93
+ * @private
94
+ * @requires <a href="http://nodejs.org/api/fs.html">fs</a>
95
+ * @requires <a href="http://nodejs.org/api/path.html">path</a>
96
+ */
97
+ function processInputFile ( ) {
98
+ var fs = require ( 'fs' ) ;
99
+ var path = require ( 'path' ) ;
63
100
64
- exports . main = function ( ) {
65
- if ( opts . file ) {
66
- var raw = fs . readFileSync ( path . normalize ( opts . file ) , 'utf8' ) ;
67
- var jsonMode = path . extname ( opts . file ) === '.json' || opts . json ;
68
- var name = path . basename ( ( opts . outfile || opts . file ) ) . replace ( / \. .* $ / g, '' ) ;
101
+ // getting raw files
69
102
var lex ;
70
-
71
103
if ( opts . lexfile ) {
72
104
lex = fs . readFileSync ( path . normalize ( opts . lexfile ) , 'utf8' ) ;
73
105
}
106
+ var raw = fs . readFileSync ( path . normalize ( opts . file ) , 'utf8' ) ;
74
107
75
- fs . writeFileSync ( opts . outfile || ( name + '.js' ) , processGrammar ( raw , lex , name , jsonMode ) ) ;
76
- } else {
108
+ // making best guess at json mode
109
+ opts . json = path . extname ( opts . file ) === '.json' || opts . json ;
110
+
111
+ // setting output file name and module name based on input file name
112
+ // if they aren't specified.
113
+ var name = path . basename ( ( opts . outfile || opts . file ) ) ;
114
+ /*jslint regexp: true */
115
+ name = name . replace ( / \. .* $ / g, '' ) ;
116
+ /*jslint regexp: false */
117
+ opts . outfile = opts . outfile || ( name + '.js' ) ;
118
+ if ( ! opts . moduleName && name ) {
119
+ opts . moduleName = name . replace ( / - \w / g,
120
+ function ( match ) {
121
+ return match . charAt ( 1 ) . toUpperCase ( ) ;
122
+ } ) ;
123
+ }
124
+
125
+ var parser = processGrammar ( raw , lex , opts ) ;
126
+ fs . writeFileSync ( opts . outfile , parser ) ;
127
+ }
128
+ /**
129
+ * Reads from stdin and calls the callback on the data received.
130
+ * @param {Function } cb The callback function to execute on the received
131
+ * data.
132
+ * @private
133
+ */
134
+ function readin ( cb ) {
135
+ var stdin = process . openStdin ( ) ,
136
+ data = '' ;
137
+
138
+ stdin . setEncoding ( 'utf8' ) ;
139
+ stdin . addListener ( 'data' , function ( chunk ) {
140
+ data += chunk ;
141
+ } ) ;
142
+ stdin . addListener ( 'end' , function ( ) {
143
+ cb ( data ) ;
144
+ } ) ;
145
+ }
146
+ /**
147
+ * Processes input from stdin.
148
+ * @private
149
+ */
150
+ function processStdin ( ) {
77
151
readin ( function ( raw ) {
78
- console . log ( processGrammar ( raw , null , null , opts . json ) ) ;
152
+ console . log ( processGrammar ( raw , null , opts ) ) ;
79
153
} ) ;
80
154
}
155
+
156
+ // if an input file wasn't given, assume input on stdin
157
+ if ( opts . file ) {
158
+ processInputFile ( ) ;
159
+ } else {
160
+ processStdin ( ) ;
161
+ }
81
162
} ;
163
+ /**
164
+ * Generates a parser and returns it as a string.
165
+ * @param {Object } opts Optional. An options object. Options are parser-type,
166
+ * module-type, and debug. Defaults to {}; see the description and examples for
167
+ * these optons in {@link Jison.cli.main}
168
+ * @param {String|Object } grammar The grammar to generate a parser from.
169
+ * @returns {String } Returns the generated parser as a string.
170
+ * @requires <a href="https://npmjs.org/package/jison/">jison</a>
171
+ */
172
+ cli . generateParserString = function generateParserString ( opts , grammar ) {
173
+ "use strict" ;
174
+ opts = opts || { } ;
175
+ var jison = require ( './jison.js' ) ;
176
+
177
+ var settings = grammar . options || { } ;
178
+
179
+ if ( opts [ 'parser-type' ] ) {
180
+ settings . type = opts [ 'parser-type' ] ;
181
+ }
182
+ settings . debug = opts . debug ;
183
+ if ( ! settings . moduleType ) {
184
+ settings . moduleType = opts [ 'module-type' ] ;
185
+ }
186
+
187
+ var generator = new jison . Generator ( grammar , settings ) ;
188
+ return generator . generate ( settings ) ;
189
+ } ;
190
+ /**
191
+ * Processes grammar files of various format.
192
+ * @param {String } file Contents of a jison grammar file.
193
+ * @param {String } lexFile Contents of a lexer grammar file.
194
+ * @param {Boolean } jsonMode Set to true if `file` is in json format.
195
+ * @returns {Object } Returns the parsed grammar object.
196
+ * @requires <a href="https://npmjs.org/package/ebnf-parser">ebnf-parser</a>
197
+ * @requires <a href="https://npmjs.org/package/cjson">cjson</a>
198
+ * @requires <a href="https://npmjs.org/package/lex-parser">lex-parser</a>
199
+ */
200
+ cli . processGrammars = function processGrammars ( file , lexFile , jsonMode ) {
201
+ "use strict" ;
202
+ var ebnfParser = require ( 'ebnf-parser' ) ;
203
+ var cjson = require ( 'cjson' ) ;
82
204
83
- function processGrammar ( file , lexFile , name , jsonMode ) {
84
205
var grammar ;
85
206
if ( jsonMode ) {
86
207
grammar = cjson . parse ( file ) ;
@@ -97,37 +218,87 @@ function processGrammar (file, lexFile, name, jsonMode) {
97
218
}
98
219
}
99
220
}
100
-
101
- var settings = grammar . options || { } ;
102
-
103
- if ( opts [ 'parser-type' ] ) settings . type = opts [ 'parser-type' ] ;
104
- if ( lexFile ) grammar . lex = lexParser . parse ( lexFile ) ;
105
- settings . debug = opts . debug ;
106
- if ( ! settings . moduleType ) settings . moduleType = opts [ 'module-type' ] ;
107
- if ( ! settings . moduleName && name ) {
108
- settings . moduleName = name . replace ( / - \w / g,
109
- function ( match ) {
110
- return match . charAt ( 1 ) . toUpperCase ( ) ;
111
- } ) ;
221
+ if ( lexFile ) {
222
+ grammar . lex = require ( 'lex-parser' ) . parse ( lexFile ) ;
112
223
}
224
+ return grammar ;
225
+ } ;
226
+ /**
227
+ * Initialization function, grabs commandline arguments and passes them to
228
+ * `cli.main` if this script was called from the commandline.
229
+ * @private
230
+ * @methodOf cli
231
+ * @requires <a href="https://npmjs.org/package/nomnom">nomnom</a>
232
+ */
233
+ function cli_init ( ) {
234
+ "use strict" ;
235
+ /**
236
+ * Gets options from the commandline.
237
+ * @private
238
+ * @requires <a href="https://npmjs.org/package/nomnom">nomnom</a>
239
+ */
240
+ function getCommandlineOptions ( ) {
241
+ var version = require ( '../package.json' ) . version ;
242
+ var opts = require ( "nomnom" )
243
+ . script ( 'jison' )
244
+ . option ( 'file' , {
245
+ flag : true ,
246
+ position : 0 ,
247
+ help : 'file containing a grammar'
248
+ } )
249
+ . option ( 'lexfile' , {
250
+ flag : true ,
251
+ position : 1 ,
252
+ help : 'file containing a lexical grammar'
253
+ } )
254
+ . option ( 'json' , {
255
+ abbr : 'j' ,
256
+ flag : true ,
257
+ help : 'force jison to expect a grammar in JSON format'
258
+ } )
259
+ . option ( 'outfile' , {
260
+ abbr : 'o' ,
261
+ metavar : 'FILE' ,
262
+ help : 'Filename and base module name of the generated parser'
263
+ } )
264
+ . option ( 'debug' , {
265
+ abbr : 't' ,
266
+ flag : true ,
267
+ default :
268
+ false ,
269
+ help : 'Debug mode'
270
+ } )
271
+ . option ( 'module-type' , {
272
+ abbr : 'm' ,
273
+ default :
274
+ 'commonjs' ,
275
+ metavar : 'TYPE' ,
276
+ help : 'The type of module to generate (commonjs, amd, js)'
277
+ } )
278
+ . option ( 'parser-type' , {
279
+ abbr : 'p' ,
280
+ default :
281
+ 'lalr' ,
282
+ metavar : 'TYPE' ,
283
+ help : 'The type of algorithm to use for the parser (lr0, slr,' +
284
+ 'lalr, lr)'
285
+ } )
286
+ . option ( 'version' , {
287
+ abbr : 'V' ,
288
+ flag : true ,
289
+ help : 'print version and exit' ,
290
+ callback : function ( ) {
291
+ return version ;
292
+ }
293
+ } ) . parse ( ) ;
294
+
295
+ return opts ;
296
+ } // end of getCommandlineOptions
113
297
114
- var generator = new jison . Generator ( grammar , settings ) ;
115
- return generator . generate ( settings ) ;
116
- }
117
-
118
- function readin ( cb ) {
119
- var stdin = process . openStdin ( ) ,
120
- data = '' ;
121
-
122
- stdin . setEncoding ( 'utf8' ) ;
123
- stdin . addListener ( 'data' , function ( chunk ) {
124
- data += chunk ;
125
- } ) ;
126
- stdin . addListener ( 'end' , function ( ) {
127
- cb ( data ) ;
128
- } ) ;
298
+ if ( require . main === module ) {
299
+ var opts = getCommandlineOptions ( ) ;
300
+ cli . main ( opts ) ;
301
+ }
129
302
}
130
303
131
- if ( require . main === module )
132
- exports . main ( ) ;
133
-
304
+ cli_init ( ) ;
0 commit comments