or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-compilation.mdcli.mdgenerated-parsers.mdgrammar-parsing.mdindex.mdparser-generation.md

generated-parsers.mddocs/

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

```