0
# Command Line Interface
1
2
Command-line tools for generating parsers, testing grammars, and working with Peggy from the terminal. The Peggy CLI provides comprehensive functionality for parser development workflows.
3
4
## Capabilities
5
6
### CLI Interface
7
8
Main command-line interface class that handles argument parsing and command execution.
9
10
```typescript { .api }
11
class PeggyCLI extends Command {
12
/**
13
* Create CLI instance with optional custom stdio streams
14
* @param stdio - Custom streams for testing (optional)
15
*/
16
constructor(stdio?: Stdio);
17
18
/**
19
* Parse command line arguments asynchronously
20
* @returns Promise resolving to configured CLI instance
21
* @throws {CommanderError} If command line arguments are invalid
22
*/
23
parseAsync(): Promise<PeggyCLI>;
24
25
/**
26
* Execute the main CLI functionality
27
* @returns Promise resolving to exit code (0 for success, 1 for error)
28
*/
29
main(): Promise<number>;
30
31
/** Parser options for generation */
32
parserOptions: SourceOptionsBase<"ast">;
33
/** Program options for execution */
34
progOptions: ProgOptions;
35
/** Standard input/output streams */
36
std: Stdio;
37
}
38
39
/**
40
* Standard I/O interface for CLI
41
*/
42
interface Stdio {
43
in: Readable;
44
out: Writable;
45
err: Writable;
46
}
47
48
/**
49
* Command-line parsing error
50
*/
51
class CommanderError extends Error {
52
code: string;
53
exitCode: number;
54
}
55
56
/**
57
* Invalid argument error
58
*/
59
class InvalidArgumentError extends CommanderError {
60
argument: string;
61
value: any;
62
reason: string;
63
}
64
```
65
66
**Basic CLI Usage:**
67
68
```bash
69
# Generate parser from grammar file
70
peggy grammar.peggy
71
72
# Generate parser with specific output file
73
peggy grammar.peggy -o parser.js
74
75
# Generate CommonJS module
76
peggy grammar.peggy --format commonjs
77
78
# Generate with allowed start rules
79
peggy grammar.peggy --allowed-start-rules rule1,rule2,rule3
80
81
# Enable caching for better performance
82
peggy grammar.peggy --cache
83
84
# Generate with tracing enabled
85
peggy grammar.peggy --trace
86
```
87
88
### Command Line Options
89
90
The Peggy CLI supports extensive options for configuring parser generation:
91
92
```bash
93
# Input and Output
94
peggy [options] [input_file...] # Grammar files to read (default: stdin)
95
peggy [options] <grammar_file> -o <output_file>
96
97
# Format Options
98
--format <format> # Output format: amd, bare, commonjs, es, globals, umd (default: commonjs)
99
-e, --export-var <variable> # Global variable name (for globals/umd formats)
100
101
# Parser Options
102
--allowed-start-rules <rules> # Comma-separated list of allowed start rules (use '*' for all)
103
--cache # Enable result caching for better performance
104
--trace # Enable parser tracing for debugging
105
106
# Module Dependencies
107
-d, --dependency <dependency> # Module dependency (format: variable:module)
108
-D, --dependencies <json> # Dependencies as JSON object
109
110
# Output Control
111
-o, --output <file> # Output file (default: auto-generated from input)
112
--ast # Output grammar AST instead of parser code
113
--dts # Create TypeScript declaration file
114
115
# Source Maps
116
-m, --source-map [mapfile] # Generate source map file or inline
117
118
# Testing and Development
119
-t, --test <text> # Test parser with given text
120
-T, --test-file <filename> # Test parser with file contents
121
-S, --start-rule <rule> # Start rule for testing
122
-w, --watch # Watch input files and regenerate on changes
123
124
# Advanced Options
125
--plugin <module> # Load plugin modules
126
--extra-options <options> # Additional JSON options for generate()
127
-c, --extra-options-file <file> # Load additional options from file
128
--return-types <typeInfo> # Type information for rules (JSON)
129
--verbose # Enable verbose logging
130
131
# Help and Information
132
-h, --help # Display help information
133
-v, --version # Display version number
134
```
135
136
**Advanced CLI Examples:**
137
138
```bash
139
# Generate ES module with dependencies
140
peggy grammar.peggy \
141
--format es \
142
--dependency "fs:fs" \
143
--dependency "path:path" \
144
-o parser.mjs
145
146
# Generate UMD module with global variable
147
peggy grammar.peggy \
148
--format umd \
149
--export-var MyParser \
150
-o parser.umd.js
151
152
# Generate with multiple start rules and caching
153
peggy grammar.peggy \
154
--allowed-start-rules "expression,statement,program" \
155
--cache \
156
--trace \
157
-o parser.js
158
159
# Generate source with inline source map
160
peggy grammar.peggy \
161
--output-format source-with-inline-map \
162
-o parser.js
163
```
164
165
### CLI Error Handling
166
167
The CLI provides detailed error reporting for both command-line and grammar errors:
168
169
```bash
170
# Grammar syntax errors
171
$ peggy invalid.peggy
172
Error: Expected "!", "$", "&", "(", ".", "@", character class, comment, end of line, identifier, literal, or whitespace but "#" found.
173
--> invalid.peggy:3:9
174
|
175
3 | start = # 'a';
176
| ^
177
178
# Grammar semantic errors
179
$ peggy undefined-rule.peggy
180
Error: Rule "undefined_rule" is not defined
181
--> undefined-rule.peggy:1:9
182
|
183
1 | start = undefined_rule
184
| ^^^^^^^^^^^^^
185
186
# Command line errors
187
$ peggy --format invalid grammar.peggy
188
Error: Invalid format: invalid
189
Valid formats: amd, bare, commonjs, es, globals, umd
190
191
$ peggy --allowed-start-rules nonexistent grammar.peggy
192
Error: Unknown start rule "nonexistent"
193
```
194
195
### Programmatic CLI Usage
196
197
Using the CLI classes programmatically for custom build tools and integrations:
198
199
```typescript { .api }
200
import { PeggyCLI, CommanderError, InvalidArgumentError } from "peggy/bin/peggy.js";
201
202
async function generateParser(args: string[]): Promise<number> {
203
try {
204
// Create CLI instance with custom arguments
205
process.argv = ["node", "peggy", ...args];
206
207
const cli = new PeggyCLI();
208
await cli.parseAsync();
209
210
// Execute CLI functionality
211
const exitCode = await cli.main();
212
return exitCode;
213
214
} catch (error) {
215
if (error instanceof CommanderError) {
216
console.error("CLI Error:", error.message);
217
return error.exitCode;
218
} else if (error instanceof InvalidArgumentError) {
219
console.error(`Invalid argument ${error.argument}: ${error.reason}`);
220
return 1;
221
} else {
222
console.error("Unexpected error:", error);
223
return 1;
224
}
225
}
226
}
227
```
228
229
**Programmatic Usage Example:**
230
231
```typescript
232
import { PeggyCLI } from "peggy/bin/peggy.js";
233
234
async function buildParser() {
235
// Simulate command line arguments
236
const args = [
237
"my-grammar.peggy",
238
"--format", "commonjs",
239
"--cache",
240
"--allowed-start-rules", "expression,statement",
241
"-o", "dist/parser.js"
242
];
243
244
const exitCode = await generateParser(args);
245
246
if (exitCode === 0) {
247
console.log("Parser generated successfully");
248
} else {
249
console.error("Parser generation failed");
250
}
251
}
252
```
253
254
### Integration with Build Tools
255
256
Examples of integrating Peggy CLI with common build tools:
257
258
**npm scripts (package.json):**
259
260
```json
261
{
262
"scripts": {
263
"build:parser": "peggy src/grammar.peggy -o lib/parser.js --format commonjs --cache",
264
"build:parser:es": "peggy src/grammar.peggy -o dist/parser.mjs --format es",
265
"build:parsers": "npm run build:parser && npm run build:parser:es",
266
"watch:parser": "nodemon --watch src/grammar.peggy --exec 'npm run build:parser'"
267
},
268
"devDependencies": {
269
"peggy": "^5.0.6",
270
"nodemon": "^3.0.0"
271
}
272
}
273
```
274
275
**Makefile:**
276
277
```makefile
278
# Parser generation targets
279
lib/parser.js: src/grammar.peggy
280
peggy $< -o $@ --format commonjs --cache
281
282
dist/parser.mjs: src/grammar.peggy
283
peggy $< -o $@ --format es
284
285
dist/parser.umd.js: src/grammar.peggy
286
peggy $< -o $@ --format umd --export-var MyParser
287
288
# Build all parser variants
289
parsers: lib/parser.js dist/parser.mjs dist/parser.umd.js
290
291
# Clean generated files
292
clean:
293
rm -f lib/parser.js dist/parser.mjs dist/parser.umd.js
294
295
.PHONY: parsers clean
296
```
297
298
**Gulp task:**
299
300
```javascript
301
const { spawn } = require('child_process');
302
const gulp = require('gulp');
303
304
function buildParser() {
305
return new Promise((resolve, reject) => {
306
const peggy = spawn('peggy', [
307
'src/grammar.peggy',
308
'-o', 'lib/parser.js',
309
'--format', 'commonjs',
310
'--cache'
311
]);
312
313
peggy.on('close', (code) => {
314
if (code === 0) {
315
resolve();
316
} else {
317
reject(new Error(`Peggy exited with code ${code}`));
318
}
319
});
320
});
321
}
322
323
gulp.task('parser', buildParser);
324
325
gulp.task('watch:parser', () => {
326
gulp.watch('src/grammar.peggy', gulp.series('parser'));
327
});
328
```
329
330
### CLI Configuration Files
331
332
While Peggy CLI doesn't support configuration files directly, you can create wrapper scripts for complex configurations:
333
334
**peggy-config.js:**
335
336
```javascript
337
#!/usr/bin/env node
338
const { PeggyCLI } = require('peggy/bin/peggy.js');
339
340
const configurations = {
341
development: [
342
'src/grammar.peggy',
343
'--format', 'commonjs',
344
'--trace',
345
'--cache',
346
'-o', 'lib/parser.dev.js'
347
],
348
349
production: [
350
'src/grammar.peggy',
351
'--format', 'es',
352
'--cache',
353
'-o', 'dist/parser.js'
354
],
355
356
browser: [
357
'src/grammar.peggy',
358
'--format', 'umd',
359
'--export-var', 'MyParser',
360
'-o', 'dist/parser.umd.js'
361
]
362
};
363
364
async function build(env = 'development') {
365
const config = configurations[env];
366
if (!config) {
367
console.error(`Unknown environment: ${env}`);
368
process.exit(1);
369
}
370
371
process.argv = ['node', 'peggy', ...config];
372
373
try {
374
const cli = new PeggyCLI();
375
await cli.parseAsync();
376
const exitCode = await cli.main();
377
process.exit(exitCode);
378
} catch (error) {
379
console.error('Build failed:', error.message);
380
process.exit(1);
381
}
382
}
383
384
// Usage: node peggy-config.js [development|production|browser]
385
const env = process.argv[2] || 'development';
386
build(env);
387
```
388
389
**Usage:**
390
391
```bash
392
# Use configuration script
393
node peggy-config.js development
394
node peggy-config.js production
395
node peggy-config.js browser
396
397
# Or add to package.json scripts
398
npm run build:dev # node peggy-config.js development
399
npm run build:prod # node peggy-config.js production
400
npm run build:browser # node peggy-config.js browser
401
```