0
# Grammar Management
1
2
Grammar representation and compilation system for working with context-free grammars and production rules.
3
4
## Capabilities
5
6
### Grammar Class
7
8
Represents a compiled grammar with rules and metadata.
9
10
```javascript { .api }
11
/**
12
* Create a new grammar from rules and start symbol
13
* @param rules - Array of Rule instances
14
* @param start - Start symbol name (defaults to first rule's name)
15
*/
16
class Grammar {
17
constructor(rules: Rule[], start?: string);
18
}
19
20
/**
21
* Grammar instance properties
22
*/
23
interface Grammar {
24
/** Array of all grammar rules */
25
rules: Rule[];
26
/** Start symbol name */
27
start: string;
28
/** Rules indexed by name for fast lookup */
29
byName: {[name: string]: Rule[]};
30
/** Associated lexer (if any) */
31
lexer?: object;
32
}
33
```
34
35
**Usage Examples:**
36
37
```javascript
38
const nearley = require("nearley");
39
40
// Create rules
41
const rules = [
42
new nearley.Rule("expr", ["number"], id => id[0]),
43
new nearley.Rule("expr", ["expr", "+", "expr"], data => data[0] + data[2]),
44
new nearley.Rule("number", [/[0-9]+/], data => parseInt(data[0]))
45
];
46
47
// Create grammar
48
const grammar = new nearley.Grammar(rules, "expr");
49
console.log("Start symbol:", grammar.start);
50
console.log("Total rules:", grammar.rules.length);
51
```
52
53
### Grammar From Compiled
54
55
Create grammar from compiled grammar objects (generated by nearleyc).
56
57
```javascript { .api }
58
/**
59
* Create Grammar from compiled grammar object
60
* @param rules - Compiled grammar object with ParserRules and metadata
61
* @param start - Optional start symbol override
62
* @returns Grammar instance ready for parsing
63
*/
64
static Grammar.fromCompiled(rules: object, start?: string): Grammar;
65
```
66
67
**Usage Examples:**
68
69
```javascript
70
const nearley = require("nearley");
71
72
// Load compiled grammar (generated with nearleyc)
73
const compiledGrammar = require("./my-grammar.js");
74
75
// Create grammar instance
76
const grammar = nearley.Grammar.fromCompiled(compiledGrammar);
77
78
// Grammar is ready to use with parser
79
const parser = new nearley.Parser(grammar);
80
81
// Access grammar properties
82
console.log("Grammar start:", grammar.start);
83
console.log("Grammar rules:", grammar.rules.length);
84
console.log("Has lexer:", !!grammar.lexer);
85
```
86
87
### Rule Class
88
89
Represents individual production rules in the grammar.
90
91
```javascript { .api }
92
/**
93
* Create a new grammar rule
94
* @param name - Left-hand side symbol name
95
* @param symbols - Right-hand side symbols array
96
* @param postprocess - Optional postprocessing function
97
*/
98
class Rule {
99
constructor(name: string, symbols: any[], postprocess?: Function);
100
}
101
102
/**
103
* Rule instance properties
104
*/
105
interface Rule {
106
/** Unique rule identifier */
107
id: number;
108
/** Left-hand side symbol name */
109
name: string;
110
/** Right-hand side symbols */
111
symbols: any[];
112
/** Postprocessing function */
113
postprocess?: Function;
114
}
115
116
/**
117
* Static rule counter
118
*/
119
static Rule.highestId: number;
120
```
121
122
**Usage Examples:**
123
124
```javascript
125
const nearley = require("nearley");
126
127
// Simple terminal rule
128
const numberRule = new nearley.Rule(
129
"number",
130
[/[0-9]+/],
131
data => parseInt(data[0])
132
);
133
134
// Rule with multiple symbols
135
const addRule = new nearley.Rule(
136
"expr",
137
["expr", "+", "expr"],
138
data => data[0] + data[2]
139
);
140
141
// Rule with no postprocessor
142
const parenRule = new nearley.Rule(
143
"expr",
144
["(", "expr", ")"],
145
data => data[1] // Extract middle element
146
);
147
148
console.log("Rule name:", numberRule.name);
149
console.log("Rule symbols:", numberRule.symbols);
150
console.log("Rule ID:", numberRule.id);
151
```
152
153
### Rule String Representation
154
155
```javascript { .api }
156
/**
157
* Convert rule to string representation
158
* @param withCursorAt - Optional position to show cursor (for debugging)
159
* @returns String representation like "expr → number + expr"
160
*/
161
toString(withCursorAt?: number): string;
162
```
163
164
**Usage Examples:**
165
166
```javascript
167
const rule = new nearley.Rule("expr", ["number", "+", "expr"]);
168
169
// Basic string representation
170
console.log(rule.toString());
171
// Output: "expr → number + expr"
172
173
// With cursor for debugging (shows parse position)
174
console.log(rule.toString(1));
175
// Output: "expr → number ● + expr"
176
177
console.log(rule.toString(3));
178
// Output: "expr → number + expr ●"
179
```
180
181
### Working with Compiled Grammars
182
183
When working with grammars compiled by nearleyc, the structure includes additional metadata.
184
185
```javascript { .api }
186
/**
187
* Compiled grammar object structure (generated by nearleyc)
188
*/
189
interface CompiledGrammar {
190
/** Parser rules array */
191
ParserRules: object[];
192
/** Start symbol name */
193
ParserStart: string;
194
/** Associated lexer */
195
Lexer?: object;
196
}
197
```
198
199
**Usage Examples:**
200
201
```javascript
202
// Example of manually creating a grammar equivalent to compiled output
203
const manualGrammar = {
204
ParserRules: [
205
{
206
name: "expr",
207
symbols: ["number"],
208
postprocess: id => id[0]
209
},
210
{
211
name: "expr",
212
symbols: ["expr", {literal: "+"}, "expr"],
213
postprocess: data => data[0] + data[2]
214
}
215
],
216
ParserStart: "expr"
217
};
218
219
const grammar = nearley.Grammar.fromCompiled(manualGrammar);
220
221
// Grammar symbols can be:
222
// - Strings (non-terminals): "expr", "number"
223
// - Objects with literal: {literal: "+"}
224
// - RegExp objects: /[0-9]+/
225
// - Objects with test function: {test: (char) => char === 'x'}
226
// - Objects with type (for lexer tokens): {type: "NUMBER"}
227
```
228
229
### Grammar Inspection
230
231
```javascript { .api }
232
/**
233
* Access grammar rules by name
234
*/
235
interface Grammar {
236
byName: {[name: string]: Rule[]};
237
}
238
```
239
240
**Usage Examples:**
241
242
```javascript
243
const grammar = nearley.Grammar.fromCompiled(compiledGrammar);
244
245
// Find all rules for a specific symbol
246
const exprRules = grammar.byName["expr"];
247
console.log(`Found ${exprRules.length} rules for 'expr'`);
248
249
exprRules.forEach((rule, i) => {
250
console.log(`Rule ${i + 1}: ${rule.toString()}`);
251
});
252
253
// Check if symbol exists in grammar
254
if (grammar.byName["statement"]) {
255
console.log("Grammar includes 'statement' rules");
256
}
257
258
// List all non-terminal symbols
259
const symbols = Object.keys(grammar.byName);
260
console.log("Grammar symbols:", symbols);
261
```
262
263
## Integration with Lexers
264
265
```javascript { .api }
266
/**
267
* Grammar with lexer integration
268
*/
269
interface GrammarWithLexer extends Grammar {
270
lexer: object;
271
}
272
```
273
274
**Usage Examples:**
275
276
```javascript
277
const moo = require("moo");
278
279
// Create a lexer
280
const lexer = moo.compile({
281
number: /[0-9]+/,
282
plus: "+",
283
ws: {match: /\s+/, lineBreaks: true}
284
});
285
286
// In compiled grammar, lexer is attached
287
const grammarWithLexer = nearley.Grammar.fromCompiled({
288
ParserRules: [/* rules using lexer tokens */],
289
ParserStart: "expr",
290
Lexer: lexer
291
});
292
293
console.log("Grammar has lexer:", !!grammarWithLexer.lexer);
294
295
// Parser will use the attached lexer
296
const parser = new nearley.Parser(grammarWithLexer);
297
```