0
# Parsing and Matching
1
2
Grammar parsing capabilities with support for incremental parsing, detailed error reporting, and trace visualization.
3
4
## Imports
5
6
```javascript
7
import { grammar } from "ohm-js";
8
```
9
10
For TypeScript:
11
12
```typescript
13
import { grammar, Grammar, MatchResult, Matcher, Interval, RuleInfo, LineAndColumnInfo } from "ohm-js";
14
```
15
16
## Capabilities
17
18
### Grammar Interface
19
20
Core interface for compiled grammar objects with parsing and semantic capabilities.
21
22
```typescript { .api }
23
/**
24
* An Ohm Grammar compiled from source code
25
*/
26
interface Grammar {
27
/** Name of the grammar */
28
name: string;
29
/** Parent grammar if this extends another grammar */
30
superGrammar: Grammar;
31
/** Dictionary of rule definitions in this grammar */
32
rules: {[ruleName: string]: RuleInfo};
33
34
/** Return true if the grammar is a built-in grammar, otherwise false */
35
isBuiltIn(): boolean;
36
37
/**
38
* Try to match input with this grammar, returning a MatchResult
39
* @param input - String to parse
40
* @param startRule - Optional rule name to start matching from
41
* @returns MatchResult indicating success or failure
42
*/
43
match(input: string, startRule?: string): MatchResult;
44
45
/**
46
* Create a new Matcher object which supports incrementally matching
47
* this grammar against a changing input string
48
* @returns Matcher instance for incremental parsing
49
*/
50
matcher(): Matcher;
51
52
/**
53
* Like match() except returns a trace object whose toString() returns
54
* a summary of each parsing step useful for debugging
55
* @param input - String to parse
56
* @param startRule - Optional rule name to start matching from
57
* @returns Trace object with debugging information
58
*/
59
trace(input: string, startRule?: string): Object;
60
61
/**
62
* Create a new Semantics object for this Grammar
63
* @returns Empty semantics instance
64
*/
65
createSemantics(): Semantics;
66
67
/**
68
* Create a new Semantics object for this Grammar that inherits all
69
* of the operations and attributes in superSemantics
70
* @param superSemantics - Parent semantics to inherit from
71
* @returns Extended semantics instance
72
*/
73
extendSemantics(superSemantics: Semantics): Semantics;
74
}
75
```
76
77
**Usage Examples:**
78
79
```javascript
80
import { grammar } from "ohm-js";
81
82
const g = grammar(`
83
Calculator {
84
expr = number ("+" number)*
85
number = digit+
86
}
87
`);
88
89
// Basic matching
90
const match = g.match("2+3+4");
91
if (match.succeeded()) {
92
console.log("Parsing succeeded!");
93
}
94
95
// Match with specific start rule
96
const numberMatch = g.match("42", "number");
97
98
// Check if grammar is built-in
99
console.log("Is built-in:", g.isBuiltIn()); // false
100
```
101
102
### Match Results
103
104
Result object returned by grammar match operations containing success/failure status and error information.
105
106
```typescript { .api }
107
/**
108
* Result of Grammar#match operation
109
*/
110
interface MatchResult {
111
/**
112
* True iff match succeeded
113
*/
114
succeeded(): boolean;
115
116
/**
117
* True iff match did not succeed
118
*/
119
failed(): boolean;
120
121
/**
122
* If match failed contains an error message indicating where and
123
* why the match failed. This message is suitable for end users of a
124
* language (i.e., people who do not have access to the grammar source).
125
*/
126
message?: string;
127
128
/**
129
* If match failed contains an abbreviated version of this.message that
130
* does not include an excerpt from the invalid input.
131
*/
132
shortMessage?: string;
133
134
/**
135
* If this MatchResult is a failure, returns an Interval indicating
136
* the position of the rightmost failure.
137
*/
138
getInterval(): Interval;
139
}
140
```
141
142
**Usage Examples:**
143
144
```javascript
145
const match = grammar.match("invalid input");
146
147
if (match.failed()) {
148
console.error("Parse error:", match.message);
149
console.error("Short error:", match.shortMessage);
150
151
const errorPos = match.getInterval();
152
console.error("Error at position:", errorPos.startIdx);
153
}
154
```
155
156
### Incremental Parsing
157
158
Matcher objects support incremental parsing for use in editors and IDEs where the input changes frequently.
159
160
```typescript { .api }
161
/**
162
* Matcher objects are used to incrementally match a changing input
163
* against a Grammar, e.g. in an editor or IDE.
164
*/
165
interface Matcher {
166
/** The grammar this matcher uses */
167
grammar: Grammar;
168
169
/**
170
* Return the current input string
171
*/
172
getInput(): string;
173
174
/**
175
* Set the input string to `str`
176
* @param str - New input string
177
*/
178
setInput(str: string): void;
179
180
/**
181
* Edit the current input string, replacing the characters between
182
* `startIdx` and `endIdx` with `str`
183
* @param startIdx - Start position of replacement
184
* @param endIdx - End position of replacement
185
* @param str - Replacement string
186
* @returns This matcher for chaining
187
*/
188
replaceInputRange(startIdx: number, endIdx: number, str: string): Matcher;
189
190
/**
191
* Like Grammar#match, but operates incrementally
192
* @param optStartRule - Optional start rule name
193
* @returns MatchResult from current input
194
*/
195
match(optStartRule?: string): MatchResult;
196
197
/**
198
* Like Grammar#trace, but operates incrementally
199
* @param optStartRule - Optional start rule name
200
* @returns Trace object for debugging
201
*/
202
trace(optStartRule?: string): Object;
203
}
204
```
205
206
**Usage Examples:**
207
208
```javascript
209
const matcher = grammar.matcher();
210
211
// Set initial input
212
matcher.setInput("2 + 3");
213
let result = matcher.match();
214
215
// Edit the input incrementally
216
matcher.replaceInputRange(0, 1, "5"); // Changes "2 + 3" to "5 + 3"
217
result = matcher.match();
218
219
// Get current input
220
console.log("Current input:", matcher.getInput());
221
```
222
223
### Rule Information
224
225
Metadata about individual grammar rules.
226
227
```typescript { .api }
228
interface RuleInfo {
229
/** Parsing expression body of the rule */
230
body: PExpr;
231
/** Formal parameter names for parameterized rules */
232
formals: string[];
233
/** Description string from grammar source */
234
description: string;
235
/** Source interval where rule is defined */
236
source: Interval;
237
}
238
```
239
240
### Interval Information
241
242
Represents a subset of a string with position and content information.
243
244
```typescript { .api }
245
/**
246
* An Interval represents a subset of a string
247
*/
248
interface Interval {
249
/** The string containing the interval */
250
sourceString: string;
251
/** The start index of the interval in `sourceString` */
252
startIdx: number;
253
/** The end index of the interval in `sourceString` */
254
endIdx: number;
255
/** Contents of interval */
256
contents: string;
257
258
/** Returns a new Interval at the start of this one */
259
collapsedLeft(): Interval;
260
/** Returns a new Interval at the end of this one */
261
collapsedRight(): Interval;
262
/** Returns a new Interval that covers this and all argument Intervals */
263
coverageWith(...intervals: Interval[]): Interval;
264
/** Returns a nicely-formatted string describing the start of the Interval */
265
getLineAndColumnMessage(): string;
266
/** Returns structure with line and column number information */
267
getLineAndColumn(): LineAndColumnInfo;
268
/** Returns array of intervals representing the difference operation */
269
minus(that: Interval): Interval[];
270
/** Returns a new Interval relative to another interval */
271
relativeTo(that: Interval): Interval;
272
/** Returns a new Interval with whitespace trimmed from both ends */
273
trimmed(): Interval;
274
/** Returns a new Interval with given length at startIdx + offset */
275
subInterval(offset: number, len: number): Interval;
276
}
277
278
interface LineAndColumnInfo {
279
offset: number;
280
lineNum: number;
281
colNum: number;
282
line: string;
283
prevLine: string;
284
nextLine: string;
285
toString(...ranges: number[][]): string;
286
}
287
```
288
289
## Error Handling and Debugging
290
291
### Trace Support
292
293
Ohm provides detailed tracing capabilities for debugging grammar matching:
294
295
```javascript
296
// Get detailed trace information
297
const trace = grammar.trace("invalid input");
298
console.log(trace.toString()); // Prints step-by-step parsing trace
299
```
300
301
### Error Messages
302
303
Match failures provide human-readable error messages:
304
305
```javascript
306
const match = grammar.match("2 +"); // Incomplete expression
307
308
if (match.failed()) {
309
// Full error message with context
310
console.error(match.message);
311
312
// Shorter error without input excerpt
313
console.error(match.shortMessage);
314
315
// Get error position for highlighting
316
const errorInterval = match.getInterval();
317
console.error(`Error at line ${errorInterval.getLineAndColumn().lineNum}`);
318
}
319
```