0
# Parse Tree API
1
2
The ANTLR4 parse tree API provides comprehensive functionality for building, navigating, and manipulating parse trees using visitor and listener patterns.
3
4
## Capabilities
5
6
### Parse Tree Interfaces
7
8
Core interfaces defining the structure of parse trees.
9
10
```java { .api }
11
/**
12
* Base interface for all parse tree nodes
13
*/
14
public interface ParseTree extends SyntaxTree {
15
/** Get parent node */
16
ParseTree getParent();
17
18
/** Get child node at index */
19
ParseTree getChild(int i);
20
21
/** Get number of children */
22
int getChildCount();
23
24
/** Accept visitor for tree traversal */
25
<T> T accept(ParseTreeVisitor<? extends T> visitor);
26
27
/** Get text representation of subtree */
28
String getText();
29
30
/** Get text with spaces between tokens */
31
String toStringTree();
32
33
/** Get source interval for this node */
34
Interval getSourceInterval();
35
}
36
37
/**
38
* Parse tree node representing parser rule invocation
39
*/
40
public interface RuleNode extends ParseTree {
41
/** Get rule context for this node */
42
RuleContext getRuleContext();
43
}
44
45
/**
46
* Parse tree leaf node representing terminal/token
47
*/
48
public interface TerminalNode extends ParseTree {
49
/** Get token for this terminal node */
50
Token getSymbol();
51
}
52
53
/**
54
* Parse tree node representing syntax error
55
*/
56
public interface ErrorNode extends TerminalNode {
57
// Inherits from TerminalNode
58
}
59
```
60
61
### Parser Rule Context
62
63
Context classes providing detailed information about rule invocations.
64
65
```java { .api }
66
/**
67
* Parse tree node for parser rules with context information
68
*/
69
public class ParserRuleContext extends RuleContext implements RuleNode {
70
/** Parent context */
71
public ParserRuleContext parent;
72
73
/** State when rule was invoked */
74
public int invokingState;
75
76
/** List of child nodes */
77
public List<ParseTree> children;
78
79
/** Start token for this rule */
80
public Token start;
81
82
/** Stop token for this rule */
83
public Token stop;
84
85
/** Exception that caused rule to exit */
86
public RecognitionException exception;
87
88
/** Add terminal child node */
89
public void addChild(TerminalNode t);
90
91
/** Add rule child node */
92
public void addChild(RuleContext ruleInvocation);
93
94
/** Remove last child */
95
public void removeLastChild();
96
97
/** Add error node child */
98
public void addErrorNode(ErrorNode errorNode);
99
100
/** Add child at specific index */
101
public void addChild(int index, ParseTree child);
102
103
/** Get child of specific type */
104
public <T extends ParseTree> T getChild(Class<T> ctxType, int i);
105
106
/** Get terminal child */
107
public TerminalNode getToken(int ttype, int i);
108
109
/** Get all terminal children of type */
110
public List<TerminalNode> getTokens(int ttype);
111
112
/** Get rule child by type */
113
public <T extends ParserRuleContext> T getRuleContext(Class<T> ctxType, int i);
114
115
/** Get all rule children of type */
116
public <T extends ParserRuleContext> List<T> getRuleContexts(Class<T> ctxType);
117
118
/** Accept visitor */
119
@Override
120
public <T> T accept(ParseTreeVisitor<? extends T> visitor);
121
122
/** Get text from start to stop token */
123
@Override
124
public String getText();
125
126
/** Convert subtree to string with parser info */
127
public String toStringTree(Parser parser);
128
129
/** Convert subtree to string with rule names */
130
public String toStringTree(List<String> ruleNames);
131
132
/** Get source interval */
133
@Override
134
public Interval getSourceInterval();
135
}
136
137
/**
138
* Base class for rule contexts
139
*/
140
public class RuleContext {
141
/** Parent rule context */
142
public RuleContext parent;
143
144
/** Invoking state */
145
public int invokingState;
146
147
/** Calculate depth in parse tree */
148
public int depth();
149
150
/** Check if context is empty */
151
public boolean isEmpty();
152
153
/** Get source interval */
154
public Interval getSourceInterval();
155
156
/** Get rule index */
157
public int getRuleIndex();
158
159
/** Get invoking state */
160
public int getInvokingState();
161
162
/** Set invoking state */
163
public void setInvokingState(int invokingState);
164
165
/** Set parent context */
166
public void setParent(RuleContext parent);
167
168
/** Get parent context */
169
public RuleContext getParent();
170
171
/** Get payload (returns this) */
172
public RuleContext getPayload();
173
174
/** Get text representation */
175
public String getText();
176
177
/** Convert to string tree */
178
public String toStringTree();
179
}
180
```
181
182
### Visitor Pattern
183
184
Interface and base class for implementing the visitor pattern on parse trees.
185
186
```java { .api }
187
/**
188
* Visitor pattern interface for parse tree traversal
189
*/
190
public interface ParseTreeVisitor<T> {
191
/** Visit parse tree node and return result */
192
T visit(ParseTree tree);
193
194
/** Visit all children of rule node */
195
T visitChildren(RuleNode node);
196
197
/** Visit terminal node */
198
T visitTerminal(TerminalNode node);
199
200
/** Visit error node */
201
T visitErrorNode(ErrorNode node);
202
}
203
204
/**
205
* Base implementation of visitor pattern with default behavior
206
*/
207
public abstract class AbstractParseTreeVisitor<T> implements ParseTreeVisitor<T> {
208
/** Visit tree node, delegating to appropriate method */
209
@Override
210
public T visit(ParseTree tree) {
211
return tree.accept(this);
212
}
213
214
/** Visit all children and return result of last non-null visit */
215
@Override
216
public T visitChildren(RuleNode node) {
217
T result = defaultResult();
218
int n = node.getChildCount();
219
for (int i = 0; i < n; i++) {
220
if (!shouldVisitNextChild(node, result)) {
221
break;
222
}
223
224
ParseTree c = node.getChild(i);
225
T childResult = c.accept(this);
226
result = aggregateResult(result, childResult);
227
}
228
return result;
229
}
230
231
/** Visit terminal node (default returns defaultResult()) */
232
@Override
233
public T visitTerminal(TerminalNode node) {
234
return defaultResult();
235
}
236
237
/** Visit error node (default returns defaultResult()) */
238
@Override
239
public T visitErrorNode(ErrorNode node) {
240
return defaultResult();
241
}
242
243
/** Default result value */
244
protected T defaultResult() {
245
return null;
246
}
247
248
/** Aggregate results from multiple children */
249
protected T aggregateResult(T aggregate, T nextResult) {
250
return nextResult;
251
}
252
253
/** Determine if should visit next child */
254
protected boolean shouldVisitNextChild(RuleNode node, T currentResult) {
255
return true;
256
}
257
}
258
```
259
260
**Usage Example:**
261
262
```java
263
import org.antlr.v4.runtime.tree.*;
264
265
// Custom visitor implementation
266
public class MyVisitor extends MyBaseVisitor<String> {
267
@Override
268
public String visitExpr(MyParser.ExprContext ctx) {
269
if (ctx.getChildCount() == 3) {
270
String left = visit(ctx.getChild(0));
271
String op = ctx.getChild(1).getText();
272
String right = visit(ctx.getChild(2));
273
return "(" + left + " " + op + " " + right + ")";
274
}
275
return visitChildren(ctx);
276
}
277
278
@Override
279
public String visitTerminal(TerminalNode node) {
280
return node.getText();
281
}
282
}
283
284
// Use visitor
285
ParseTree tree = parser.expr();
286
MyVisitor visitor = new MyVisitor();
287
String result = visitor.visit(tree);
288
```
289
290
### Listener Pattern
291
292
Interface and walker for implementing the listener pattern on parse trees.
293
294
```java { .api }
295
/**
296
* Listener pattern interface for parse tree events
297
*/
298
public interface ParseTreeListener {
299
/** Called when entering any rule */
300
void enterEveryRule(ParserRuleContext ctx);
301
302
/** Called when exiting any rule */
303
void exitEveryRule(ParserRuleContext ctx);
304
305
/** Called when visiting terminal node */
306
void visitTerminal(TerminalNode node);
307
308
/** Called when visiting error node */
309
void visitErrorNode(ErrorNode node);
310
}
311
312
/**
313
* Tree walker utility for traversing parse trees with listeners
314
*/
315
public class ParseTreeWalker {
316
/** Default walker instance */
317
public static final ParseTreeWalker DEFAULT = new ParseTreeWalker();
318
319
/** Walk tree with listener, calling enter/exit methods */
320
public void walk(ParseTreeListener listener, ParseTree t) {
321
if (t instanceof ErrorNode) {
322
listener.visitErrorNode((ErrorNode) t);
323
return;
324
} else if (t instanceof TerminalNode) {
325
listener.visitTerminal((TerminalNode) t);
326
return;
327
}
328
329
RuleNode r = (RuleNode) t;
330
ParserRuleContext ctx = (ParserRuleContext) r.getRuleContext();
331
332
enterRule(listener, r);
333
334
for (int i = 0; i < t.getChildCount(); i++) {
335
walk(listener, t.getChild(i));
336
}
337
338
exitRule(listener, r);
339
}
340
341
/** Enter rule node */
342
protected void enterRule(ParseTreeListener listener, RuleNode r) {
343
ParserRuleContext ctx = (ParserRuleContext) r.getRuleContext();
344
listener.enterEveryRule(ctx);
345
ctx.enterRule(listener);
346
}
347
348
/** Exit rule node */
349
protected void exitRule(ParseTreeListener listener, RuleNode r) {
350
ParserRuleContext ctx = (ParserRuleContext) r.getRuleContext();
351
ctx.exitRule(listener);
352
listener.exitEveryRule(ctx);
353
}
354
}
355
```
356
357
**Usage Example:**
358
359
```java
360
import org.antlr.v4.runtime.tree.*;
361
362
// Custom listener implementation
363
public class MyListener extends MyBaseListener {
364
@Override
365
public void enterExpr(MyParser.ExprContext ctx) {
366
System.out.println("Entering expression: " + ctx.getText());
367
}
368
369
@Override
370
public void exitExpr(MyParser.ExprContext ctx) {
371
System.out.println("Exiting expression: " + ctx.getText());
372
}
373
374
@Override
375
public void visitTerminal(TerminalNode node) {
376
System.out.println("Terminal: " + node.getText());
377
}
378
}
379
380
// Use listener
381
ParseTree tree = parser.expr();
382
ParseTreeWalker walker = new ParseTreeWalker();
383
MyListener listener = new MyListener();
384
walker.walk(listener, tree);
385
```
386
387
### Tree Utility Methods
388
389
Static utility methods for common parse tree operations.
390
391
```java { .api }
392
/**
393
* Static utility methods for parse trees
394
*/
395
public class Trees {
396
/** Convert tree to string representation */
397
public static String toStringTree(ParseTree t);
398
399
/** Convert tree to string using parser */
400
public static String toStringTree(ParseTree t, Parser parser);
401
402
/** Convert tree to string using rule names */
403
public static String toStringTree(ParseTree t, List<String> ruleNames);
404
405
/** Get all children of a parse tree node */
406
public static List<ParseTree> getChildren(ParseTree t);
407
408
/** Get all ancestors of a parse tree node */
409
public static List<ParseTree> getAncestors(ParseTree t);
410
411
/** Find all nodes with specified token type */
412
public static Collection<ParseTree> findAllTokenNodes(ParseTree t, int ttype);
413
414
/** Find all nodes with specified rule index */
415
public static Collection<ParseTree> findAllRuleNodes(ParseTree t, int ruleIndex);
416
417
/** Find all descendant nodes with specified rule index */
418
public static Collection<ParseTree> descendants(ParseTree t);
419
420
/** Get node ancestors up to specified rule type */
421
public static ParserRuleContext getAncestorOfType(ParserRuleContext ctx, Class<? extends ParserRuleContext> ruleType);
422
423
/** Strip parse tree to text only */
424
public static String stripParseTree(ParseTree t);
425
}
426
```
427
428
### Parse Tree Properties
429
430
Associate arbitrary data with parse tree nodes.
431
432
```java { .api }
433
/**
434
* Associate arbitrary data with parse tree nodes
435
*/
436
public class ParseTreeProperty<V> {
437
/** Associate value with parse tree node */
438
public V put(ParseTree node, V value);
439
440
/** Get value associated with parse tree node */
441
public V get(ParseTree node);
442
443
/** Remove association for parse tree node */
444
public V removeFrom(ParseTree node);
445
}
446
```
447
448
**Usage Example:**
449
450
```java
451
import org.antlr.v4.runtime.tree.*;
452
453
// Create property map
454
ParseTreeProperty<String> nodeTypes = new ParseTreeProperty<>();
455
456
// Associate data with nodes
457
nodeTypes.put(exprNode, "arithmetic");
458
nodeTypes.put(termNode, "operand");
459
460
// Retrieve data
461
String type = nodeTypes.get(exprNode); // "arithmetic"
462
```
463
464
## Pattern Matching
465
466
XPath-like querying of parse trees.
467
468
```java { .api }
469
/**
470
* XPath-like querying of parse trees
471
*/
472
public class XPath {
473
/** Find all nodes matching XPath expression */
474
public static Collection<ParseTree> findAll(ParseTree tree, String xpath, Parser parser);
475
476
/** Compile XPath expression */
477
public static XPathElement[] split(String path);
478
}
479
```
480
481
**Usage Example:**
482
483
```java
484
import org.antlr.v4.runtime.tree.xpath.XPath;
485
486
// Find all identifier nodes
487
Collection<ParseTree> ids = XPath.findAll(tree, "//ID", parser);
488
489
// Find specific rule contexts
490
Collection<ParseTree> exprs = XPath.findAll(tree, "//expr", parser);
491
492
// Complex path
493
Collection<ParseTree> nodes = XPath.findAll(tree, "//expr/*/ID", parser);
494
```
495
496
## Usage Patterns
497
498
### Basic Tree Traversal
499
500
```java
501
import org.antlr.v4.runtime.tree.*;
502
503
// Parse and get tree
504
ParseTree tree = parser.startRule();
505
506
// Simple visitor
507
MyVisitor visitor = new MyVisitor();
508
String result = visitor.visit(tree);
509
510
// Simple listener
511
ParseTreeWalker walker = new ParseTreeWalker();
512
MyListener listener = new MyListener();
513
walker.walk(listener, tree);
514
```
515
516
### Complex Tree Analysis
517
518
```java
519
import org.antlr.v4.runtime.tree.*;
520
521
// Analyze tree structure
522
List<ParseTree> children = Trees.getChildren(tree);
523
List<ParseTree> ancestors = Trees.getAncestors(someNode);
524
525
// Find specific nodes
526
Collection<ParseTree> identifiers = Trees.findAllTokenNodes(tree, MyLexer.ID);
527
Collection<ParseTree> expressions = Trees.findAllRuleNodes(tree, MyParser.RULE_expr);
528
529
// Convert to string
530
String treeString = Trees.toStringTree(tree, parser);
531
System.out.println(treeString);
532
```
533
534
### Tree Modification and Analysis
535
536
```java
537
import org.antlr.v4.runtime.tree.*;
538
539
// Associate metadata with nodes
540
ParseTreeProperty<Integer> depths = new ParseTreeProperty<>();
541
ParseTreeProperty<String> nodeLabels = new ParseTreeProperty<>();
542
543
// Visitor that computes and stores depth
544
public class DepthVisitor extends MyBaseVisitor<Integer> {
545
@Override
546
public Integer visitExpr(MyParser.ExprContext ctx) {
547
int maxChildDepth = 0;
548
for (int i = 0; i < ctx.getChildCount(); i++) {
549
Integer childDepth = visit(ctx.getChild(i));
550
if (childDepth != null && childDepth > maxChildDepth) {
551
maxChildDepth = childDepth;
552
}
553
}
554
int thisDepth = maxChildDepth + 1;
555
depths.put(ctx, thisDepth);
556
return thisDepth;
557
}
558
559
@Override
560
public Integer visitTerminal(TerminalNode node) {
561
depths.put(node, 0);
562
return 0;
563
}
564
}
565
566
// Use visitor and check results
567
DepthVisitor depthVisitor = new DepthVisitor();
568
depthVisitor.visit(tree);
569
570
Integer rootDepth = depths.get(tree);
571
System.out.println("Tree depth: " + rootDepth);
572
```