0
# AST Node Framework
1
2
Complete Abstract Syntax Tree representation of Velocity templates with 40+ specialized node types for expressions, directives, references, and control structures. The AST framework provides a comprehensive visitor pattern implementation for traversing and analyzing parsed Velocity templates.
3
4
## Capabilities
5
6
### Base Node Interface
7
8
Core interface implemented by all Velocity AST nodes, providing visitor pattern support and tree navigation.
9
10
```java { .api }
11
/**
12
* Base interface for all Velocity AST nodes.
13
* Extends PMD's Node interface with Velocity-specific visitor support.
14
*/
15
public interface VmNode extends Node {
16
17
/**
18
* Accept a visitor and invoke the appropriate visit method.
19
* Central method for visitor pattern implementation.
20
* @param visitor The visitor to accept
21
* @param data Context data passed through visitor traversal
22
* @return Result from visitor method execution
23
*/
24
Object jjtAccept(VmParserVisitor visitor, Object data);
25
26
/**
27
* Accept a visitor for all child nodes.
28
* Convenience method for traversing child nodes.
29
* @param visitor The visitor to apply to children
30
* @param data Context data passed through visitor traversal
31
* @return Result from child visitor executions
32
* @deprecated This method is not useful, the logic for combining
33
* children values should be present on the visitor, not the node
34
*/
35
@Deprecated
36
Object childrenAccept(VmParserVisitor visitor, Object data);
37
38
/**
39
* Get a specific child node by index.
40
* @param index Zero-based index of child node
41
* @return Child node at specified index
42
* @throws IndexOutOfBoundsException if index is invalid
43
*/
44
VmNode getChild(int index);
45
46
/**
47
* Get the parent node of this node.
48
* @return Parent node, or null if this is the root node
49
*/
50
VmNode getParent();
51
52
/**
53
* Get an iterable over all child nodes.
54
* @return Iterable for traversing child nodes
55
*/
56
Iterable<? extends VmNode> children();
57
}
58
```
59
60
### Base Node Implementation
61
62
Abstract base class providing common functionality for all Velocity AST nodes.
63
64
```java { .api }
65
/**
66
* Abstract base implementation for all Velocity AST nodes.
67
* Provides common functionality including position tracking, token access,
68
* and tree structure management.
69
* @deprecated Marked as internal API - use VmNode interface instead
70
*/
71
@Deprecated
72
@InternalApi
73
public abstract class AbstractVmNode extends AbstractJjtreeNode implements VmNode {
74
75
/**
76
* Called when node is opened during parsing.
77
* Part of JavaCC tree construction lifecycle.
78
*/
79
public void jjtOpen();
80
81
/**
82
* Called when node is closed during parsing.
83
* Part of JavaCC tree construction lifecycle.
84
*/
85
public void jjtClose();
86
87
/**
88
* Get the first token associated with this node.
89
* @return First token of this node's source text
90
*/
91
public Token getFirstToken();
92
93
/**
94
* Get the last token associated with this node.
95
* @return Last token of this node's source text
96
*/
97
public Token getLastToken();
98
99
/**
100
* Get the literal text representation of this node.
101
* @return String representation of the node's source text
102
*/
103
public String literal();
104
105
/**
106
* Get the node type identifier.
107
* @return Integer constant identifying the node type
108
*/
109
public int getType();
110
111
/**
112
* Set additional information for this node.
113
* @param info Integer value for node-specific metadata
114
*/
115
public void setInfo(int info);
116
117
/**
118
* Get additional information for this node.
119
* @return Integer value containing node-specific metadata
120
*/
121
public int getInfo();
122
123
/**
124
* Mark this node as invalid due to parse errors.
125
*/
126
public void setInvalid();
127
128
/**
129
* Check if this node is marked as invalid.
130
* @return true if node has parse errors, false otherwise
131
*/
132
public boolean isInvalid();
133
134
/**
135
* Get the line number where this node begins.
136
* @return Line number (1-based) in source template
137
*/
138
public int getLine();
139
140
/**
141
* Get the column number where this node begins.
142
* @return Column number (1-based) in source template
143
*/
144
public int getColumn();
145
146
/**
147
* Get the name of the template containing this node.
148
* @return Template filename or identifier
149
*/
150
public String getTemplateName();
151
152
/**
153
* Dump the AST structure starting from this node.
154
* @param prefix String prefix for indentation
155
* @param alreadyDumped Whether parent nodes have been dumped
156
* @param writer Output writer for dump content
157
*/
158
public void dump(String prefix, boolean alreadyDumped, Writer writer);
159
}
160
```
161
162
### Visitor Pattern Implementation
163
164
Default visitor adapter providing base traversal logic for all AST node types.
165
166
```java { .api }
167
/**
168
* Default implementation of VmParserVisitor that provides base traversal
169
* logic for all Velocity AST node types. Extend this class to create
170
* custom visitors that only override specific visit methods.
171
*/
172
public class VmParserVisitorAdapter implements VmParserVisitor {
173
174
/**
175
* Default visit method for base VmNode interface.
176
* @param node The node being visited
177
* @param data Context data passed through traversal
178
* @return null by default, subclasses may return meaningful values
179
*/
180
public Object visit(VmNode node, Object data);
181
182
// Visit methods for all specific node types
183
public Object visit(ASTprocess node, Object data);
184
public Object visit(ASTReference node, Object data);
185
public Object visit(ASTDirective node, Object data);
186
public Object visit(ASTMethod node, Object data);
187
public Object visit(ASTIndex node, Object data);
188
189
// Mathematical operation nodes
190
public Object visit(ASTAddNode node, Object data);
191
public Object visit(ASTSubtractNode node, Object data);
192
public Object visit(ASTMulNode node, Object data);
193
public Object visit(ASTDivNode node, Object data);
194
public Object visit(ASTModNode node, Object data);
195
public Object visit(ASTMathNode node, Object data);
196
197
// Logical operation nodes
198
public Object visit(ASTOrNode node, Object data);
199
public Object visit(ASTAndNode node, Object data);
200
public Object visit(ASTNotNode node, Object data);
201
202
// Comparison operation nodes
203
public Object visit(ASTEQNode node, Object data);
204
public Object visit(ASTNENode node, Object data);
205
public Object visit(ASTLTNode node, Object data);
206
public Object visit(ASTGTNode node, Object data);
207
public Object visit(ASTLENode node, Object data);
208
public Object visit(ASTGENode node, Object data);
209
210
// Control flow nodes
211
public Object visit(ASTIfStatement node, Object data);
212
public Object visit(ASTElseStatement node, Object data);
213
public Object visit(ASTElseIfStatement node, Object data);
214
public Object visit(ASTForeachStatement node, Object data);
215
public Object visit(ASTSetDirective node, Object data);
216
public Object visit(ASTBlock node, Object data);
217
218
// Expression and assignment nodes
219
public Object visit(ASTExpression node, Object data);
220
public Object visit(ASTAssignment node, Object data);
221
222
// Data structure nodes
223
public Object visit(ASTMap node, Object data);
224
public Object visit(ASTObjectArray node, Object data);
225
public Object visit(ASTIntegerRange node, Object data);
226
227
// Content and text nodes
228
public Object visit(ASTText node, Object data);
229
public Object visit(ASTTextblock node, Object data);
230
public Object visit(ASTComment node, Object data);
231
232
// Literal value nodes
233
public Object visit(ASTFloatingPointLiteral node, Object data);
234
public Object visit(ASTIntegerLiteral node, Object data);
235
public Object visit(ASTStringLiteral node, Object data);
236
public Object visit(ASTTrue node, Object data);
237
public Object visit(ASTFalse node, Object data);
238
239
// Identifier and word nodes
240
public Object visit(ASTIdentifier node, Object data);
241
public Object visit(ASTWord node, Object data);
242
243
// Escape and directive nodes
244
public Object visit(ASTEscape node, Object data);
245
public Object visit(ASTEscapedDirective node, Object data);
246
}
247
```
248
249
## Key AST Node Types
250
251
### Reference Nodes
252
253
Represent Velocity variable references (`$variable`, `$object.property`).
254
255
```java { .api }
256
/**
257
* AST node representing Velocity variable references.
258
* Handles both simple references ($var) and complex references ($obj.prop).
259
*/
260
public class ASTReference extends AbstractVmNode {
261
262
/**
263
* Get the root identifier string of the reference.
264
* For $user.name, returns "user".
265
* @return Root variable name
266
*/
267
public String getRootString();
268
269
/**
270
* Set the literal text representation of this reference.
271
* @param literal String representation to set
272
*/
273
public void setLiteral(String literal);
274
275
/**
276
* Get the literal text representation of this reference.
277
* @return Complete reference string including $ prefix
278
*/
279
public String literal();
280
}
281
```
282
283
### Directive Nodes
284
285
Represent Velocity directives (`#if`, `#foreach`, `#set`, etc.).
286
287
```java { .api }
288
/**
289
* AST node representing Velocity directives.
290
* Handles all directive types including control flow and utility directives.
291
*/
292
public class ASTDirective extends AbstractVmNode {
293
// Inherits all AbstractVmNode functionality
294
// Specific directive behavior determined by child nodes and context
295
}
296
```
297
298
### Method Call Nodes
299
300
Represent method invocations within Velocity templates.
301
302
```java { .api }
303
/**
304
* AST node representing method calls in Velocity templates.
305
* Handles both simple method calls and chained method invocations.
306
*/
307
public class ASTMethod extends AbstractVmNode {
308
// Inherits all AbstractVmNode functionality
309
// Method name and parameters accessible via child nodes
310
}
311
```
312
313
### Mathematical Operation Nodes
314
315
Specialized nodes for different mathematical operations.
316
317
```java { .api }
318
/**
319
* AST node representing addition operations.
320
*/
321
public class ASTAddNode extends AbstractVmNode {
322
// Inherits position tracking and tree navigation
323
// Left and right operands accessible via child nodes
324
}
325
326
/**
327
* AST node representing subtraction operations.
328
*/
329
public class ASTSubtractNode extends AbstractVmNode;
330
331
/**
332
* AST node representing multiplication operations.
333
*/
334
public class ASTMulNode extends AbstractVmNode;
335
336
/**
337
* AST node representing division operations.
338
*/
339
public class ASTDivNode extends AbstractVmNode;
340
341
/**
342
* AST node representing modulo operations.
343
*/
344
public class ASTModNode extends AbstractVmNode;
345
346
/**
347
* Base AST node for mathematical operations.
348
*/
349
public class ASTMathNode extends AbstractVmNode;
350
```
351
352
### Escape Sequence Nodes
353
354
Handle Velocity escape sequences and escaped directives.
355
356
```java { .api }
357
/**
358
* AST node representing escape sequences in Velocity templates.
359
* Handles backslash escaping of special characters.
360
*/
361
public class ASTEscape extends AbstractVmNode {
362
// Inherits all AbstractVmNode functionality
363
// Escaped character accessible via token information
364
}
365
```
366
367
## Utility Classes
368
369
### Node Utilities
370
371
Helper methods for common AST node operations.
372
373
```java { .api }
374
/**
375
* Utility class providing helper methods for AST node operations.
376
* Contains static methods for common node analysis tasks.
377
*/
378
public class NodeUtils {
379
// Static utility methods for node analysis and manipulation
380
// Implementation details vary based on specific utility needs
381
}
382
```
383
384
## Usage Examples
385
386
### Basic AST Traversal
387
388
```java
389
import net.sourceforge.pmd.lang.vm.ast.VmParserVisitorAdapter;
390
import net.sourceforge.pmd.lang.vm.ast.ASTReference;
391
import net.sourceforge.pmd.lang.vm.ast.ASTDirective;
392
393
public class TemplateAnalyzer extends VmParserVisitorAdapter {
394
395
@Override
396
public Object visit(ASTReference node, Object data) {
397
String refName = node.getRootString();
398
System.out.println("Found reference: " + refName +
399
" at line " + node.getLine());
400
return super.visit(node, data);
401
}
402
403
@Override
404
public Object visit(ASTDirective node, Object data) {
405
System.out.println("Found directive at line " + node.getLine());
406
// Traverse child nodes to analyze directive structure
407
return node.childrenAccept(this, data);
408
}
409
}
410
```
411
412
### Node Information Access
413
414
```java
415
import net.sourceforge.pmd.lang.vm.ast.VmNode;
416
417
public void analyzeNode(VmNode node) {
418
// Position information
419
int line = node.getLine();
420
int column = node.getColumn();
421
String template = node.getTemplateName();
422
423
// Content information
424
String literal = node.literal();
425
Token firstToken = node.getFirstToken();
426
Token lastToken = node.getLastToken();
427
428
// Tree navigation
429
VmNode parent = node.getParent();
430
int childCount = node.getNumChildren();
431
432
// Child iteration
433
for (VmNode child : node.children()) {
434
analyzeNode(child);
435
}
436
}
437
```
438
439
### Custom Visitor Implementation
440
441
```java
442
import net.sourceforge.pmd.lang.vm.ast.VmParserVisitor;
443
444
public class CustomVelocityVisitor implements VmParserVisitor {
445
446
@Override
447
public Object visit(VmNode node, Object data) {
448
// Default handling for any node type
449
return node.childrenAccept(this, data);
450
}
451
452
@Override
453
public Object visit(ASTReference node, Object data) {
454
// Custom handling for variable references
455
String refName = node.getRootString();
456
if (isProblematicReference(refName)) {
457
reportIssue(node, "Problematic reference: " + refName);
458
}
459
return null;
460
}
461
462
// Implement only the visit methods you need
463
// Unimplemented methods will use default behavior
464
465
private boolean isProblematicReference(String refName) {
466
return refName != null && refName.length() > 50;
467
}
468
469
private void reportIssue(VmNode node, String message) {
470
System.err.println(message + " at " +
471
node.getTemplateName() + ":" + node.getLine());
472
}
473
}
474
```