0
# Generated Parsers
1
2
Interface and capabilities of parsers generated by Peggy, including parsing options, error handling, and tracing functionality. Generated parsers provide a consistent API regardless of the original grammar complexity.
3
4
## Capabilities
5
6
### Parser Interface
7
8
The standard interface implemented by all generated parsers, providing parsing functionality and metadata access.
9
10
```typescript { .api }
11
interface Parser {
12
/** Array of rule names that can be used as start rules */
13
StartRules: string[];
14
/** Syntax error class for this specific parser */
15
SyntaxError: typeof parser.SyntaxError;
16
17
/**
18
* Parse input text using the generated parser
19
* @param input - Text to parse
20
* @param options - Parsing options
21
* @returns Parsed result (type depends on grammar actions)
22
* @throws {SyntaxError} If input doesn't match grammar
23
*/
24
parse(input: string, options?: ParserOptions): any;
25
26
/**
27
* Parse input in library mode (for internal use)
28
* @param input - Text to parse
29
* @param options - Parsing options with library mode enabled
30
* @returns Library results with internal state
31
*/
32
parse(
33
input: string,
34
options: Omit<ParserOptions, "peg$library"> & { peg$library: true }
35
): LibraryResults;
36
}
37
```
38
39
**Basic Parser Usage:**
40
41
```typescript
42
import { generate } from "peggy";
43
44
// Generate parser from grammar
45
const grammar = `
46
Expression
47
= Term (("+" / "-") Term)*
48
49
Term
50
= Factor (("*" / "/") Factor)*
51
52
Factor
53
= "(" Expression ")"
54
/ Number
55
56
Number
57
= digits:[0-9]+ { return parseInt(digits.join(""), 10); }
58
`;
59
60
const parser = generate(grammar);
61
62
// Check available start rules
63
console.log("Start rules:", parser.StartRules); // ["Expression"]
64
65
// Parse expressions
66
try {
67
const result1 = parser.parse("2 + 3 * 4");
68
const result2 = parser.parse("(1 + 2) * 3");
69
const result3 = parser.parse("42");
70
71
console.log("Results:", result1, result2, result3);
72
} catch (error) {
73
if (error instanceof parser.SyntaxError) {
74
console.error("Parse error:", error.message);
75
}
76
}
77
```
78
79
### Parsing Options
80
81
Configuration options for controlling parser behavior during parsing operations.
82
83
```typescript { .api }
84
interface ParserOptions {
85
/** Additional options for parser extensions */
86
[key: string]: any;
87
88
/** Source identifier for error reporting */
89
grammarSource?: any;
90
/** Rule name to start parsing from */
91
startRule?: string;
92
/** Tracer for debugging parse operations */
93
tracer?: ParserTracer;
94
95
// Internal options (advanced usage):
96
/** Enable library mode for internal operations */
97
peg$library?: boolean;
98
/** Starting position offset in input */
99
peg$currPos?: number;
100
/** Silent failure count for internal use */
101
peg$silentFails?: number;
102
/** Expected items for error reporting */
103
peg$maxFailExpected?: parser.Expectation[];
104
}
105
```
106
107
**Advanced Parsing Options:**
108
109
```typescript
110
import { generate } from "peggy";
111
112
const grammar = `
113
program = statement*
114
statement = assignment / expression
115
assignment = name:identifier "=" value:expression { return { type: "assign", name, value }; }
116
expression = number / identifier
117
identifier = [a-zA-Z][a-zA-Z0-9]* { return text(); }
118
number = [0-9]+ { return parseInt(text(), 10); }
119
`;
120
121
const parser = generate(grammar, {
122
allowedStartRules: ["program", "statement", "expression"]
123
});
124
125
// Parse with different start rules
126
const program = parser.parse("x = 42", { startRule: "program" });
127
const statement = parser.parse("x = 42", { startRule: "statement" });
128
const expression = parser.parse("42", { startRule: "expression" });
129
130
// Parse with source information for better errors
131
try {
132
parser.parse("invalid syntax", {
133
grammarSource: "user-input.txt",
134
startRule: "program"
135
});
136
} catch (error) {
137
console.error(`Error in ${error.location.source}:`, error.message);
138
}
139
```
140
141
### Parse Tracing
142
143
Debugging functionality that allows monitoring of parse operations and rule matching.
144
145
```typescript { .api }
146
interface ParserTracer {
147
/**
148
* Called for each significant parse event
149
* @param event - Parse event information
150
*/
151
trace(event: ParserTracerEvent): void;
152
}
153
154
/**
155
* Parse event types for tracing
156
*/
157
type ParserTracerEvent
158
= { type: "rule.enter"; rule: string; location: LocationRange }
159
| { type: "rule.fail"; rule: string; location: LocationRange }
160
| { type: "rule.match"; rule: string; result: any; location: LocationRange };
161
```
162
163
**Tracing Usage Example:**
164
165
```typescript
166
import { generate } from "peggy";
167
168
const grammar = `
169
start = word+
170
word = letters:[a-z]+ " "? { return letters.join(""); }
171
`;
172
173
const parser = generate(grammar, { trace: true });
174
175
// Custom tracer for debugging
176
const tracer = {
177
trace(event) {
178
const pos = `${event.location.start.line}:${event.location.start.column}`;
179
180
switch (event.type) {
181
case "rule.enter":
182
console.log(`→ ${event.rule} at ${pos}`);
183
break;
184
case "rule.match":
185
console.log(`✓ ${event.rule} matched:`, event.result);
186
break;
187
case "rule.fail":
188
console.log(`✗ ${event.rule} failed at ${pos}`);
189
break;
190
}
191
}
192
};
193
194
// Parse with tracing enabled
195
const result = parser.parse("hello world", { tracer });
196
```
197
198
### Error Handling
199
200
Comprehensive error reporting with location information and expectation details.
201
202
```typescript { .api }
203
/**
204
* Parse error with detailed information
205
*/
206
class SyntaxError extends globalThis.SyntaxError {
207
/** Location where parse failed */
208
location: LocationRange;
209
/** What the parser expected at the failure point */
210
expected: parser.Expectation[] | null;
211
/** What was actually found at the failure point */
212
found: string | null;
213
214
constructor(
215
message: string,
216
expected: parser.Expectation[] | null,
217
found: string | null,
218
location: LocationRange
219
);
220
221
/**
222
* Format error with source context
223
* @param sources - Source text mapping for formatting
224
* @returns Formatted error message with source lines
225
*/
226
format(sources: SourceText[]): string;
227
228
/**
229
* Build human-readable message from expectations
230
* @param expected - Array of expected items
231
* @param found - What was found instead
232
* @returns Human-readable error description
233
*/
234
static buildMessage(expected: parser.Expectation[], found: string): string;
235
}
236
```
237
238
**Error Handling Example:**
239
240
```typescript
241
import { generate } from "peggy";
242
243
const grammar = `
244
json_value = object / array / string / number / boolean / null
245
object = "{" "}" { return {}; }
246
array = "[" "]" { return []; }
247
string = '"' chars:[^"]* '"' { return chars.join(""); }
248
number = digits:[0-9]+ { return parseInt(digits.join(""), 10); }
249
boolean = "true" { return true; } / "false" { return false; }
250
null = "null" { return null; }
251
`;
252
253
const parser = generate(grammar);
254
255
try {
256
const result = parser.parse('{"invalid": json}');
257
} catch (error) {
258
if (error instanceof parser.SyntaxError) {
259
console.log("Parse failed at line", error.location.start.line);
260
console.log("Column", error.location.start.column);
261
console.log("Expected:", error.expected?.map(e => e.type));
262
console.log("Found:", error.found);
263
264
// Format with source context
265
const formatted = error.format([{
266
source: "input.json",
267
text: '{"invalid": json}'
268
}]);
269
console.log("\nFormatted error:\n", formatted);
270
271
// Build custom message
272
if (error.expected && error.found) {
273
const message = parser.SyntaxError.buildMessage(error.expected, error.found);
274
console.log("Custom message:", message);
275
}
276
}
277
}
278
```
279
280
### Library Mode Results
281
282
Internal results structure returned when using library mode parsing (advanced usage).
283
284
```typescript { .api }
285
interface LibraryResults {
286
/** Parse result or failure marker */
287
peg$result: any;
288
/** Current position after parsing */
289
peg$currPos: number;
290
/** Failure marker object */
291
peg$FAILED: object;
292
/** Expected items at maximum failure position */
293
peg$maxFailExpected: parser.Expectation[];
294
/** Position of maximum failure */
295
peg$maxFailPos: number;
296
}
297
```
298
299
**Library Mode Example (Advanced):**
300
301
```typescript
302
import { generate } from "peggy";
303
304
const grammar = `
305
start = "test" { return "success"; }
306
`;
307
308
const parser = generate(grammar);
309
310
// Library mode parsing (for advanced integration)
311
const result = parser.parse("test", { peg$library: true });
312
313
if (result.peg$result !== result.peg$FAILED) {
314
console.log("Parse succeeded:", result.peg$result);
315
console.log("Consumed", result.peg$currPos, "characters");
316
} else {
317
console.log("Parse failed at position", result.peg$maxFailPos);
318
console.log("Expected:", result.peg$maxFailExpected);
319
}
320
```
321
322
### Multi-Start Rule Parsers
323
324
Working with parsers that allow multiple entry points for parsing different grammar constructs.
325
326
```typescript { .api }
327
// Generated parser with multiple start rules
328
interface MultiStartParser extends Parser {
329
StartRules: string[]; // Multiple rule names
330
}
331
```
332
333
**Multi-Start Rule Example:**
334
335
```typescript
336
import { generate } from "peggy";
337
338
const grammar = `
339
program = statement*
340
statement = assignment / expression / declaration
341
assignment = identifier "=" expression
342
declaration = "let" identifier ("=" expression)?
343
expression = addition
344
addition = multiplication (("+" / "-") multiplication)*
345
multiplication = primary (("*" / "/") primary)*
346
primary = number / identifier / "(" expression ")"
347
identifier = [a-zA-Z][a-zA-Z0-9]* { return text(); }
348
number = [0-9]+ { return parseInt(text(), 10); }
349
`;
350
351
const parser = generate(grammar, {
352
allowedStartRules: ["program", "statement", "expression"]
353
});
354
355
console.log("Available start rules:", parser.StartRules);
356
357
// Parse different constructs
358
const fullProgram = parser.parse("let x = 2 + 3", { startRule: "program" });
359
const singleStatement = parser.parse("x = 42", { startRule: "statement" });
360
const justExpression = parser.parse("2 + 3 * 4", { startRule: "expression" });
361
362
console.log("Program:", fullProgram);
363
console.log("Statement:", singleStatement);
364
console.log("Expression:", justExpression);
365
```
366
367
### Performance Considerations
368
369
Understanding parser performance characteristics and optimization options.
370
371
```typescript
372
// Caching can improve performance for complex grammars with backtracking
373
const cachedParser = generate(complexGrammar, { cache: true });
374
375
// Trace mode adds overhead - only use during development
376
const debugParser = generate(grammar, { trace: true });
377
378
// For production, use minimal options
379
const productionParser = generate(grammar, {
380
cache: false, // Disable if not needed
381
trace: false // Always disable in production
382
});
383
```
384
385
**Performance Example:**
386
387
```typescript
388
import { generate } from "peggy";
389
390
const complexGrammar = `
391
expression = choice+
392
choice = "a" expression / "b" expression / "c" expression / simple
393
simple = [0-9]+
394
`;
395
396
// Test with and without caching
397
const noCacheParser = generate(complexGrammar, { cache: false });
398
const cachedParser = generate(complexGrammar, { cache: true });
399
400
const input = "a".repeat(100) + "123"; // Pathological input
401
402
console.time("Without cache");
403
try {
404
noCacheParser.parse(input);
405
} catch (e) {
406
// Expected to fail, but measures backtracking time
407
}
408
console.timeEnd("Without cache");
409
410
console.time("With cache");
411
try {
412
cachedParser.parse(input);
413
} catch (e) {
414
// Expected to fail, but should be faster with cache
415
}
416
console.timeEnd("With cache");
417
```