or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

character-streams.mddebug-support.mderror-handling.mdindex.mdlexical-analysis.mdparsing.mdtoken-streams.mdtree-construction.md

tree-construction.mddocs/

0

# Tree Construction and Manipulation

1

2

Abstract Syntax Tree (AST) construction, traversal, and manipulation utilities. The tree package provides comprehensive support for building parse trees, ASTs, tree rewriting, and tree pattern matching.

3

4

## Capabilities

5

6

### Tree Interface

7

8

Base interface for all tree nodes providing hierarchical structure operations.

9

10

```java { .api }

11

/**

12

* Basic tree node interface

13

*/

14

public interface Tree {

15

/** Get a child at index i. */

16

public Tree getChild(int i);

17

18

/** How many children are there? If there is none, return 0. */

19

public int getChildCount();

20

21

/** Get the parent for this node; if null, implies node is root */

22

public Tree getParent();

23

24

/** Set the parent and child index; implies node does not yet have parent */

25

public void setParent(Tree t);

26

27

/** Is there an ancestor with this token type? */

28

public boolean hasAncestor(int ttype);

29

30

/** Walk up and get list of this node's ancestors. First node of

31

* list is the root and the last is the parent of this node.

32

*/

33

public List<Tree> getAncestors();

34

35

/** This node is what child index? 0..n-1 */

36

public int getChildIndex();

37

38

/** Set the child index. */

39

public void setChildIndex(int index);

40

41

/** Walk tree and visit each node, setting parent and child index. */

42

public void freshenParentAndChildIndexes();

43

44

/** Add t as child of this node. Warning: if t has no children, but

45

* child does and child isNil then this routine moves children to t via

46

* t.replaceChildren(child.children).

47

*/

48

public void addChild(Tree t);

49

50

/** Set ith child (0..n-1) to t; t must be non-null and non-nil node */

51

public void setChild(int i, Tree t);

52

53

/** Delete the child at index i (0..n-1) and return it; null if no such child */

54

public Object deleteChild(int i);

55

56

/** Delete children from start to stop and replace with t even if t is

57

* a list (nil-root tree). Num of children can increase or decrease.

58

* For huge child lists, inserting children can force walking rest of

59

* children to set their childindex; could be slow.

60

*/

61

public void replaceChildren(int startChildIndex, int stopChildIndex, Object t);

62

63

/** Indicates the node is a nil node but may still have children, meaning

64

* the tree is a flat list.

65

*/

66

public boolean isNil();

67

68

/** What is the smallest token index (indexing from 0) for this node

69

* and its children?

70

*/

71

public int getTokenStartIndex();

72

73

/** What is the largest token index (indexing from 0) for this node

74

* and its children?

75

*/

76

public int getTokenStopIndex();

77

78

public Tree dupNode();

79

80

/** Return a token type; needed for tree parsing */

81

public int getType();

82

83

public String getText();

84

85

/** In case we don't have a token payload, what is the line for errors? */

86

public int getLine();

87

88

public int getCharPositionInLine();

89

90

public String toString();

91

92

/** Print out a whole tree in LISP form. {@link #getType} is used on the

93

* node payloads to get the text for the nodes. Detect

94

* parse trees and extract data appropriately.

95

*/

96

public String toStringTree();

97

}

98

```

99

100

### Base Tree Implementation

101

102

Abstract base implementation of the Tree interface providing common functionality.

103

104

```java { .api }

105

/**

106

* Base implementation of Tree interface

107

*/

108

public abstract class BaseTree implements Tree {

109

/** Child nodes if any */

110

protected List<Tree> children;

111

112

public BaseTree();

113

public BaseTree(Tree node);

114

115

/** Get a child at index i; null if index out of range */

116

public Tree getChild(int i);

117

118

/** How many children are there? If there is none, return 0. */

119

public int getChildCount();

120

121

/** Add t as child of this node. Warning: if t has no children, but

122

* child does and child isNil then this routine moves children to t via

123

* t.replaceChildren(child.children).

124

*/

125

public void addChild(Tree t);

126

127

/** Add all elements of kids list as children of this node */

128

public void addChildren(List<Tree> kids);

129

130

/** Set ith child (0..n-1) to t; t must be non-null and non-nil node */

131

public void setChild(int i, Tree t);

132

133

/** Delete the child at index i (0..n-1) and return it; null if no such child */

134

public Object deleteChild(int i);

135

136

/** Delete children from start to stop and replace with t even if t is

137

* a list (nil-root tree). Num of children can increase or decrease.

138

* For huge child lists, inserting children can force walking rest of

139

* children to set their childindex; could be slow.

140

*/

141

public void replaceChildren(int startChildIndex, int stopChildIndex, Object t);

142

143

/** Override in a subclass to change the impl of children list */

144

protected List<Tree> createChildrenList();

145

146

/** Indicates the node is a nil node but may still have children, meaning

147

* the tree is a flat list.

148

*/

149

public boolean isNil();

150

151

/** Walk tree and visit each node, setting parent and child index. */

152

public void freshenParentAndChildIndexes();

153

154

public void freshenParentAndChildIndexesDeeply();

155

156

protected void freshenParentAndChildIndexes(int offset);

157

158

public void sanityCheckParentAndChildIndexes();

159

public void sanityCheckParentAndChildIndexes(Tree parent, int i);

160

161

/** What is the smallest token index (indexing from 0) for this node

162

* and its children?

163

*/

164

public int getTokenStartIndex();

165

166

/** What is the largest token index (indexing from 0) for this node

167

* and its children?

168

*/

169

public int getTokenStopIndex();

170

171

public abstract Tree dupNode();

172

public abstract int getType();

173

public abstract String getText();

174

175

/** In case we don't have a token payload, what is the line for errors? */

176

public int getLine();

177

public int getCharPositionInLine();

178

179

public String toString();

180

181

/** Print out a whole tree in LISP form. {@link #getType} is used on the

182

* node payloads to get the text for the nodes. Detect

183

* parse trees and extract data appropriately.

184

*/

185

public String toStringTree();

186

187

public List<Tree> getAncestors();

188

189

/** Walk up and get first ancestor with this token type. */

190

public Tree getAncestor(int ttype);

191

192

/** Return a list of all ancestors of this node. The first node of

193

* list is the root and the last is the parent of this node.

194

*/

195

public List<Tree> getAncestors();

196

197

/** Is there an ancestor with this token type? */

198

public boolean hasAncestor(int ttype);

199

200

/** Walk up and get first ancestor with this token type. */

201

public Tree getAncestor(int ttype);

202

203

/** Return a list of all ancestors of this node. The first node of

204

* list is the root and the last is the parent of this node.

205

*/

206

public List<Tree> getAncestors();

207

208

public Tree getParent();

209

public void setParent(Tree t);

210

public int getChildIndex();

211

public void setChildIndex(int index);

212

}

213

```

214

215

### Common Tree

216

217

Standard tree node implementation using tokens as payloads.

218

219

```java { .api }

220

/**

221

* Default tree node implementation

222

*/

223

public class CommonTree extends BaseTree {

224

/** A single token is the payload */

225

public Token token;

226

227

/** What token indexes bracket all tokens associated with this node

228

* and below?

229

*/

230

protected int startIndex = -1, stopIndex = -1;

231

232

/** Who is the parent node of this node; if null, implies node is root */

233

public CommonTree parent;

234

235

/** What index is this node in the child list? Range: 0..n-1 */

236

public int childIndex = -1;

237

238

public CommonTree();

239

public CommonTree(CommonTree node);

240

public CommonTree(Token t);

241

242

public Token getToken();

243

244

public Tree dupNode();

245

246

/** Return a token type; needed for tree parsing */

247

public int getType();

248

249

public String getText();

250

251

/** In case we don't have a token payload, what is the line for errors? */

252

public int getLine();

253

254

public int getCharPositionInLine();

255

256

public int getTokenStartIndex();

257

public void setTokenStartIndex(int index);

258

259

public int getTokenStopIndex();

260

public void setTokenStopIndex(int index);

261

262

/** For every node in this subtree, make sure children[i] points to

263

* a child i. Walk depth first, visit bottom up. That way, all the

264

* children of a node are fixed first.

265

*/

266

public void setChildIndex(int index);

267

268

public Tree getParent();

269

public void setParent(Tree t);

270

271

public int getChildIndex();

272

273

/** Indicates the node is a nil node but may still have children, meaning

274

* the tree is a flat list.

275

*/

276

public boolean isNil();

277

278

public String toString();

279

}

280

```

281

282

**Usage Examples:**

283

284

```java

285

import org.antlr.runtime.tree.*;

286

import org.antlr.runtime.*;

287

288

// Create tree nodes

289

Token plusToken = new CommonToken(MyParser.PLUS, "+");

290

CommonTree plusNode = new CommonTree(plusToken);

291

292

Token xToken = new CommonToken(MyParser.IDENTIFIER, "x");

293

CommonTree xNode = new CommonTree(xToken);

294

295

Token yToken = new CommonToken(MyParser.IDENTIFIER, "y");

296

CommonTree yNode = new CommonTree(yToken);

297

298

// Build tree structure: + (x, y)

299

plusNode.addChild(xNode);

300

plusNode.addChild(yNode);

301

302

// Navigate tree

303

System.out.println("Root: " + plusNode.getText());

304

System.out.println("Child 0: " + plusNode.getChild(0).getText());

305

System.out.println("Child 1: " + plusNode.getChild(1).getText());

306

307

// Print tree in LISP format

308

System.out.println("Tree: " + plusNode.toStringTree());

309

310

// Check relationships

311

System.out.println("Parent of x: " + xNode.getParent().getText());

312

System.out.println("Child index of y: " + yNode.getChildIndex());

313

```

314

315

### Tree Adaptor

316

317

Interface for tree manipulation operations and customizable tree construction.

318

319

```java { .api }

320

/**

321

* Interface for tree manipulation operations

322

*/

323

public interface TreeAdaptor {

324

/** Create a tree node from Token object; for CommonTree type trees,

325

* no need to specify a Token object. The token payload should

326

* contain the appropriate type and text info.

327

*/

328

public Object create(Token payload);

329

330

/** Duplicate a tree, assuming this is a root node of a tree--

331

* duplicate everything underneath. This is done via the adaptor

332

* rather than the tree itself to handle different types of trees.

333

*/

334

public Object dupTree(Object tree);

335

336

/** Duplicate a single tree node, but not its children; single node dup. */

337

public Object dupNode(Object t);

338

339

/** Return the type; allow for later extension via subclassing. */

340

public int getType(Object t);

341

342

/** In some applications, it would be useful to track parent pointers

343

* or the index of a child. Tree and Tree adaptor interfaces are

344

* intended to be as minimal as possible.

345

*/

346

public void setText(Object t, String text);

347

348

public String getText(Object t);

349

350

/** Get the token associated with this node; if you are not using

351

* CommonTree, then you must override this in your own adaptor.

352

*/

353

public Token getToken(Object t);

354

355

/** Where are token start/stop boundaries for subtree rooted at t?

356

* The token information is not set unless you are using

357

* TokenRewriteStream to construct and emit the original or

358

* modified token stream. The adaptor is responsible for setting

359

* these values. Many implementations will use the CommonTree

360

* that tracks start/stop token indexes. If you are mixing up tree

361

* formats, then the easiest thing to do is make sure this method

362

* on your TreeAdaptor returns something that cooresponds to Token.getTokenIndex().

363

* Return -1 if you don't use tokens/tokenstream.

364

*/

365

public void setTokenBoundaries(Object t, Token startToken, Token stopToken);

366

367

public int getTokenStartIndex(Object t);

368

public int getTokenStopIndex(Object t);

369

370

/** Get a child 0..n-1 node */

371

public Object getChild(Object t, int i);

372

373

/** Set ith child (0..n-1) to t; t must be non-null and non-nil node */

374

public void setChild(Object t, int i, Object child);

375

376

/** Remove ith child and shift children down from right. */

377

public Object deleteChild(Object t, int i);

378

379

/** How many children? If 0, then this is a leaf node */

380

public int getChildCount(Object t);

381

382

/** Return an ID for this node, which is unique within the life of

383

* this TreeAdaptor. Usually it's the memory address of the node.

384

* If we're building trees from a stream, then ID should be the

385

* index in the stream.

386

*/

387

public int getUniqueID(Object node);

388

389

// REWRITE SUPPORT

390

391

/** Tell me how to create a token for use with imaginary token nodes.

392

* For example, there is probably no input symbol associated with decl

393

* node types. This method is executed when you type create(type).

394

*/

395

public Object create(int tokenType, Token fromToken);

396

public Object create(int tokenType, Token fromToken, String text);

397

public Object create(int tokenType, String text);

398

399

/** Make tree t the new root of oldRoot; oldRoot is a lost child of t. */

400

public Object becomeRoot(Object newRoot, Object oldRoot);

401

402

/** If oldRoot is a nil root, just copy or move the children to newRoot.

403

* If not a nil root, make oldRoot a child of newRoot.

404

*

405

* old=^(nil a b c), new=r yields ^(r a b c)

406

* old=^(a b c), new=r yields ^(r ^(a b c))

407

*

408

* If newRoot is a nil-rooted single child tree, use the single

409

* child as the new root node.

410

*

411

* old=^(nil a b c), new=^(nil r) yields ^(r a b c)

412

* old=^(a b c), new=^(nil r) yields ^(r ^(a b c))

413

*

414

* If oldRoot was null, it's ok, just return newRoot (even if isNil).

415

*

416

* old=null, new=r yields r

417

* old=null, new=^(nil r) yields ^(nil r)

418

*

419

* Return newRoot. Throw an exception if newRoot is not a nil node

420

* and has children. This would mean that the new root has both

421

* the oldRoot and its own children. The definition of ^(...) is that

422

* it is make the ^(a b c) the root and make the ^(a b c) a child of ^(r ...)

423

*/

424

public Object rulePostProcessing(Object root);

425

426

/** Add a child to the tree t. If child is a flat tree (a list), make all

427

* in list children of t. Warning: if t has no children, but child does

428

* and child isNil then this routine moves children to t via

429

* t.replaceChildren(child.children).

430

*/

431

public void addChild(Object t, Object child);

432

433

/** If oldRoot is a nil root, just copy or move the children to newRoot.

434

* If not a nil root, make oldRoot a child of newRoot.

435

*

436

* old=^(nil a b c), new=r yields ^(r a b c)

437

* old=^(a b c), new=r yields ^(r ^(a b c))

438

*

439

* If newRoot is a nil-rooted single child tree, use the single

440

* child as the new root node.

441

*

442

* old=^(nil a b c), new=^(nil r) yields ^(r a b c)

443

* old=^(a b c), new=^(nil r) yields ^(r ^(a b c))

444

*

445

* If oldRoot was null, it's ok, just return newRoot (even if isNil).

446

*

447

* old=null, new=r yields r

448

* old=null, new=^(nil r) yields ^(nil r)

449

*

450

* Return newRoot. Throw an exception if newRoot is not a nil node

451

* and has children. This would mean that the new root has both

452

* the oldRoot and its own children. The definition of ^(...) is that

453

* it is make the ^(a b c) the root and make the ^(a b c) a child of ^(r ...)

454

*/

455

public Object becomeRoot(Token newRoot, Object oldRoot);

456

457

/** Create a node for newRoot make it a root of oldRoot.

458

* If oldRoot is a nil root, just copy or move the children to newRoot.

459

* If not a nil root, make oldRoot a child of newRoot.

460

* Return node newRoot.

461

*/

462

public Object create(int tokenType, Token fromToken);

463

public Object create(int tokenType, Token fromToken, String text);

464

public Object create(int tokenType, String text);

465

466

/** For identifying trees.

467

*

468

* How to identify nodes so we can say "add node to a prior node"?

469

* Even becomeRoot is an issue. Use System.identityHashCode(node)

470

* usually.

471

*/

472

public int getUniqueID(Object node);

473

474

475

// TREE PARSING

476

477

/** For tree parsing, I need to know the token type of a node */

478

public int getType(Object t);

479

480

/** Node constructors can set the type of a node */

481

public void setType(Object t, int type);

482

483

public String getText(Object t);

484

485

/** Node constructors can set the text of a node */

486

public void setText(Object t, String text);

487

488

/** Return the token object from which this node was created.

489

* Currently used only for printing an error message.

490

* The error display routine in BaseRecognizer needs to

491

* display where the input the error occurred. If your

492

* tree of limitation does not store information that can

493

* lead you to the token, you can create a token filled with

494

* the appropriate information and pass that back. See

495

* BaseRecognizer.getErrorMessage().

496

*/

497

public Token getToken(Object t);

498

499

/** Where are token start/stop boundaries for subtree rooted at t?

500

* For rules that create AST nodes, this method is called on

501

* the returned AST node from every rule invocation. The result

502

* is the collapse of all child boundaries to that of the parent.

503

*/

504

public void setTokenBoundaries(Object t, Token startToken, Token stopToken);

505

506

/** Return the first token associated with this node. If this node

507

* is associated with Token objects, you can access this start

508

* token, and from there you can access the start token's input

509

* stream. Return null if no such token.

510

*/

511

public int getTokenStartIndex(Object t);

512

public int getTokenStopIndex(Object t);

513

514

/** Get a child 0..n-1 node */

515

public Object getChild(Object t, int i);

516

517

/** Set ith child (0..n-1) to t; t must be non-null and non-nil node */

518

public void setChild(Object t, int i, Object child);

519

520

/** Remove ith child and shift children down from right. */

521

public Object deleteChild(Object t, int i);

522

523

/** How many children? If 0, then this is a leaf node */

524

public int getChildCount(Object t);

525

526

/** Is the tree node considered a nil node used to make lists

527

* of child nodes?

528

*/

529

public boolean isNil(Object tree);

530

531

/** Return something analogous to the usual debug string for

532

* a parse tree such as: (+ 1 2).

533

*/

534

public String toString(Object t);

535

536

/** Return a string for an entire tree not just a node */

537

public String toString(Object t, String[] ruleNames);

538

539

/** Return a string for a range of nodes encompassed in rule r at

540

* positions begin to end (not end+1!). For example,

541

* toString(t, "expr", 2, 5) can print the tokens from

542

* expr rule invocations 2 through 5.

543

*/

544

public String toString(Object t, int begin, int end);

545

546

/** Track start/stop token for subtree root created for a rule.

547

* Only works with Tree nodes. For rules that match nothing,

548

* seems like this will yield start=i and stop=i-1 in a nil node.

549

* Might be useful info so I'll not force to be i..i.

550

*/

551

public void setTokenBoundaries(Object t, Token startToken, Token stopToken);

552

553

/** Get the token start index for this subtree; return -1 if no such index */

554

public int getTokenStartIndex(Object t);

555

556

/** Get the token stop index for this subtree; return -1 if no such index */

557

public int getTokenStopIndex(Object t);

558

559

/** Replace any child at index i (0..n-1) with t; t must be non-null and non-nil. */

560

public void setChild(Object t, int i, Object child);

561

562

/** Delete child at index i (0..n-1) and return it; null if not found. */

563

public Object deleteChild(Object t, int i);

564

565

/** Is the tree t considered a nil node used to make lists

566

* of child nodes?

567

*/

568

public boolean isNil(Object tree);

569

570

/** Return something analogous to the usual debug string for

571

* a parse tree such as: (+ 1 2).

572

*/

573

public String toString(Object t);

574

575

/** Create a new node derived from a token, with a new token type.

576

* This is invoked from an imaginary node ref on right side of a

577

* tree grammar rule, for example:

578

*

579

* This reference to NEW in tree parser...

580

* ^(NEW type identifier)

581

*

582

* must create a new node of token type NEW with text "NEW".

583

* If you are creating a string-based AST with UniversalTree for

584

* example, then a 'new' UniversalTree(NEW, "NEW") would be

585

* returned from this method.

586

*

587

* This method should be overridden. If you care about the

588

* Token object from which this node to be created is associated,

589

* override this method. Otherwise, override the String version.

590

* NOTE: the Rule.ctor(Token, String) is called by the default

591

* implementation.

592

*

593

* If you are building trees for a language like C that has

594

* no explicit list structure to represent a function call,

595

* but you would like to overlay some nodes to represent

596

* the various parts such as argument list, return value,

597

* function name, etc..., then you would return a node

598

* representing that construct.

599

*/

600

public Object create(int tokenType, Token fromToken);

601

602

/** Same as create(tokenType,fromToken) except set the text too.

603

* This is useful for converting GENERIC['"<"] to GENERIC["<";] for

604

* example, where the GENERIC node is associated with the original

605

* token from the input stream.

606

*/

607

public Object create(int tokenType, Token fromToken, String text);

608

609

/** Create a new node derived from a token, with a new token type

610

* and new text. This is invoked from an imaginary node ref on right

611

* side of a tree grammar rule, for example:

612

*

613

* This reference to NEW in tree parser...

614

* ^(NEW["foo"] type identifier)

615

*

616

* must create a new node of token type NEW with text "foo".

617

* If you are creating a string-based AST with UniversalTree for

618

* example, then a 'new' UniversalTree(NEW, "foo") would be

619

* returned from this method.

620

*/

621

public Object create(int tokenType, String text);

622

623

/** Does the tree adpator support unique IDs? how to implement adapt()

624

* depends on this. buildTree() calls adaptor.getUniqueID(node).

625

* Override if you're using your own BaseTree-derived objects.

626

*/

627

public boolean hasUniqueID(Object node);

628

629

/** For tree parsing, return the token type of a node */

630

public int getType(Object t);

631

632

public void setType(Object t, int type);

633

634

public String getText(Object t);

635

636

public void setText(Object t, String text);

637

638

/** For tree parsing, return the token object associated with node t.

639

* For BasicTree, this is just the token. For CommonTree, this is

640

* the token. For your AST nodes, this method must return the

641

* Token object from which this node was created. This is used for

642

* printing out error messages that include line/column info.

643

*

644

* Essentially, the error message is trying to figure out what Token

645

* object was associated with the erroneous AST node. One could

646

* also use a hash table to map AST nodes to tokens but I think

647

* that's overkill.

648

*/

649

public Token getToken(Object t);

650

651

/** Set the token boundaries for subtree root t. The boundaries are

652

* stored on the node as start/stop token indexes. This is done

653

* automatically when parsing with output=AST but the boundaries

654

* must be set when invoking actions manually such as tree construction

655

* in actions, building adapters, etc... When using ^(...) make syntax

656

* in actions, the form ^(root child1 ... childN) causes ANTLR to invoke

657

* the adaptor methods:

658

*

659

* r = create(type);

660

* addChild(r, child1);

661

* ...

662

* addChild(r, childN);

663

* setTokenBoundaries(r, firstToken, lastToken);

664

*

665

* If you are building ASTs manually in a translating tree parser,

666

* then you need to be careful to set the token boundaries explicitly.

667

* Look at the examples in the tree/ dir for how to do this. This

668

* method is the final method called in the ^(root ...) action so it

669

* is really where the tree knows its token boundaries.

670

*

671

* NOTE: if this is a nil root (children list then nil, start/stop

672

* are computed from start of first child and stop of last child.

673

* The nil root points into the children list, which should still

674

* point to the original tokens from your original AST.

675

*

676

* Called automatically when constructing ASTs.

677

*/

678

public void setTokenBoundaries(Object t, Token startToken, Token stopToken);

679

680

public int getTokenStartIndex(Object t);

681

public int getTokenStopIndex(Object t);

682

683

/** Replace child at position i (0..n-1) with t; t must be non-null and non-nil node. */

684

public void setChild(Object t, int i, Object child);

685

686

/** Delete child at position i (0..n-1) and shift children down from right. */

687

public Object deleteChild(Object t, int i);

688

689

/** Is the tree node t considered a nil node used to make lists

690

* of child nodes?

691

*/

692

public boolean isNil(Object tree);

693

694

/** Duplicate single node, but not its children; single node dup. */

695

public Object dupNode(Object t);

696

697

/** This method returns whatever object represents the data at this node. For

698

* example, for CommonTree, it returns the token. For your AST nodes,

699

* it could return the AST node. The only requirement is that it have a

700

* toString() method and you can print it out. This is used to print

701

* out lists of AST nodes (so that toString() is invoked on the node

702

* repeatedly).

703

*

704

* Essentially toString() is used on the returned object.

705

*

706

* Default is just toString() on whatever the node is.

707

*

708

* Override if you are using your own ast nodes.

709

*/

710

public Object getNodePayload(Object node);

711

712

/** Return something analogous to the usual debug string for a parse tree

713

* such as: (+ 1 2). Print it like a binary tree in LISP form.

714

* Return "nil" if the tree is a nil node. Do not print any parens for a

715

* nil node. The AST node type or token type is printed followed by

716

* the children.

717

*

718

* Return "nil" if t==null

719

*/

720

public String toString(Object t);

721

722

/** Return a string for an entire tree not just a node */

723

public String toString(Object t, String[] ruleNames);

724

725

/** A more verbose AST toString. Pass in a rule name vector for use with

726

* generated parsers. I computed these as integers and then constructed

727

* a String vector, but a String[] is more efficient. Null if you don't

728

* have a String[] to pass in.

729

*/

730

public String toString(Object t, String[] ruleNames);

731

}

732

```

733

734

### Common Tree Adaptor

735

736

Standard tree adaptor implementation for CommonTree nodes.

737

738

```java { .api }

739

/**

740

* Default tree adaptor implementation

741

*/

742

public class CommonTreeAdaptor extends BaseTreeAdaptor {

743

/** Duplicate a single tree node.

744

* Override if you want another kind of node to be built.

745

*/

746

public Object dupNode(Object t);

747

748

public Object create(Token payload);

749

750

/** Tell me how to create a token for use with imaginary token nodes.

751

* For example, there is probably no input symbol associated with decl

752

* node types. This method is executed when you type create(type).

753

*/

754

public Token createToken(int tokenType, String text);

755

756

/** Tell me how to create a token for use with imaginary token nodes.

757

* For example, there is probably no input symbol associated with decl

758

* node types. This method is executed when you type create int).

759

*/

760

public Token createToken(Token fromToken);

761

762

/** Track start/stop token for subtree root created for a rule.

763

* Only works with Tree nodes. For rules that match nothing,

764

* seems like this will yield start=i and stop=i-1 in a nil node.

765

* Might be useful info so I'll not force to be i..i.

766

*/

767

public void setTokenBoundaries(Object t, Token startToken, Token stopToken);

768

769

public int getTokenStartIndex(Object t);

770

771

public int getTokenStopIndex(Object t);

772

773

public String getText(Object t);

774

775

/** Tell the adaptor the type of the child token of root token t.

776

* Don't specify an invalid index i.

777

*/

778

public void setType(Object t, int type);

779

780

public int getType(Object t);

781

782

/** For tree parsing, return the token object associated with node t.

783

* This is used mainly for error reporting.

784

*/

785

public Token getToken(Object t);

786

787

/** Where are token start/stop boundaries for subtree rooted at t?

788

* This is not a method in any interface; I think the parser calls

789

* this method during AST construction. This method is also called

790

* when setting token boundaries manually such as with tree rewrite

791

* operations.

792

*/

793

public void setChild(Object t, int i, Object child);

794

795

public Object deleteChild(Object t, int i);

796

797

/** Is the tree node t considered a nil node used to make lists

798

* of child nodes?

799

*/

800

public boolean isNil(Object tree);

801

802

/** For tree parsing, I need to know the token type of a node */

803

public void setText(Object t, String text);

804

805

/** For tree parsing, I need to know the token type of a node */

806

public String getText(Object t);

807

808

/** For tree parsing, I need to know the token type of a node */

809

public void setType(Object t, int type);

810

811

public int getType(Object t);

812

813

/** For tree parsing, return the token object associated with node t.

814

* This is used mainly for error reporting.

815

*/

816

public Token getToken(Object t);

817

818

public String toString(Object t);

819

820

public String toString(Object t, String[] ruleNames);

821

}

822

```

823

824

**Usage Examples:**

825

826

```java

827

import org.antlr.runtime.tree.*;

828

import org.antlr.runtime.*;

829

830

// Create tree adaptor

831

TreeAdaptor adaptor = new CommonTreeAdaptor();

832

833

// Create nodes

834

Object root = adaptor.create(MyParser.PLUS, "+");

835

Object left = adaptor.create(MyParser.IDENTIFIER, "x");

836

Object right = adaptor.create(MyParser.NUMBER, "42");

837

838

// Build tree

839

adaptor.addChild(root, left);

840

adaptor.addChild(root, right);

841

842

// Make tree: ^(PLUS x 42)

843

System.out.println("Tree: " + adaptor.toString(root));

844

845

// Navigation

846

int childCount = adaptor.getChildCount(root);

847

Object firstChild = adaptor.getChild(root, 0);

848

String firstChildText = adaptor.getText(firstChild);

849

850

// Tree manipulation

851

Object newChild = adaptor.create(MyParser.IDENTIFIER, "y");

852

adaptor.setChild(root, 1, newChild); // Replace second child

853

854

// Create tree with token boundaries

855

Token startToken = new CommonToken(MyParser.IDENTIFIER, "x");

856

Token stopToken = new CommonToken(MyParser.NUMBER, "42");

857

adaptor.setTokenBoundaries(root, startToken, stopToken);

858

```

859

860

## Types

861

862

### Tree Node Types

863

864

```java { .api }

865

public class CommonErrorNode extends CommonTree {

866

public IntStream input;

867

public Token start;

868

public Token stop;

869

public RecognitionException trappedException;

870

871

public CommonErrorNode(TokenStream input, Token start, Token stop, RecognitionException e);

872

873

public boolean isNil();

874

public int getType();

875

public String getText();

876

public String toString();

877

}

878

879

public class ParseTree extends BaseTree {

880

public Object payload;

881

public List<Token> hiddenTokens;

882

883

public ParseTree(Object payload);

884

885

public Tree dupNode();

886

public int getType();

887

public String getText();

888

public int getTokenStartIndex();

889

public int getTokenStopIndex();

890

public String toString();

891

public String toStringWithHiddenTokens();

892

public String toInputString();

893

}

894

```

895

896

## Common Patterns

897

898

### Manual Tree Construction

899

900

```java

901

// Create tree manually: ^(PLUS ^(MULT x 2) y)

902

TreeAdaptor adaptor = new CommonTreeAdaptor();

903

904

Object plus = adaptor.create(PLUS, "+");

905

Object mult = adaptor.create(MULT, "*");

906

Object x = adaptor.create(IDENTIFIER, "x");

907

Object two = adaptor.create(NUMBER, "2");

908

Object y = adaptor.create(IDENTIFIER, "y");

909

910

// Build multiplication subtree

911

adaptor.addChild(mult, x);

912

adaptor.addChild(mult, two);

913

914

// Build addition tree

915

adaptor.addChild(plus, mult);

916

adaptor.addChild(plus, y);

917

918

System.out.println("Tree: " + adaptor.toString(plus));

919

```

920

921

### Tree Traversal

922

923

```java

924

public void walkTree(Object tree, TreeAdaptor adaptor) {

925

if (tree == null) return;

926

927

// Process current node

928

System.out.println("Node: " + adaptor.getText(tree) +

929

" Type: " + adaptor.getType(tree));

930

931

// Visit all children

932

int childCount = adaptor.getChildCount(tree);

933

for (int i = 0; i < childCount; i++) {

934

Object child = adaptor.getChild(tree, i);

935

walkTree(child, adaptor);

936

}

937

}

938

```

939

940

### Tree Copying

941

942

```java

943

public Object copyTree(Object tree, TreeAdaptor adaptor) {

944

if (tree == null) return null;

945

946

// Duplicate root node

947

Object copy = adaptor.dupNode(tree);

948

949

// Copy all children recursively

950

int childCount = adaptor.getChildCount(tree);

951

for (int i = 0; i < childCount; i++) {

952

Object child = adaptor.getChild(tree, i);

953

Object childCopy = copyTree(child, adaptor);

954

adaptor.addChild(copy, childCopy);

955

}

956

957

return copy;

958

}

959

```

960

961

### Token Boundary Management

962

963

```java

964

// Set boundaries for manually constructed trees

965

Token startToken = /* first token */;

966

Token stopToken = /* last token */;

967

968

Object tree = adaptor.create(EXPRESSION);

969

// ... add children ...

970

971

adaptor.setTokenBoundaries(tree, startToken, stopToken);

972

973

// Get boundaries later

974

int start = adaptor.getTokenStartIndex(tree);

975

int stop = adaptor.getTokenStopIndex(tree);

976

```

977

978

## Tree Utilities

979

980

### TreeWizard

981

982

Utility class for building and navigating trees using string patterns and queries.

983

984

```java { .api }

985

/**

986

* Build and navigate trees with string patterns and queries

987

*/

988

public class TreeWizard {

989

protected TreeAdaptor adaptor;

990

protected Map<String, Integer> tokenNameToTypeMap;

991

992

public interface ContextVisitor {

993

public void visit(Object t, Object parent, int childIndex, Map<String, Object> labels);

994

}

995

996

public static abstract class Visitor implements ContextVisitor {

997

public void visit(Object t, Object parent, int childIndex, Map<String, Object> labels);

998

public abstract void visit(Object t);

999

}

1000

1001

public static class TreePattern extends CommonTree {

1002

public String label;

1003

public boolean hasTextArg;

1004

public TreePattern(Token payload);

1005

}

1006

1007

public TreeWizard(TreeAdaptor adaptor);

1008

public TreeWizard(TreeAdaptor adaptor, Map<String, Integer> tokenNameToTypeMap);

1009

public TreeWizard(TreeAdaptor adaptor, String[] tokenNames);

1010

public TreeWizard(String[] tokenNames);

1011

1012

/** Compute a Map<String, Integer> that is an inverted index of

1013

* tokenNames (which maps int token types to names).

1014

*/

1015

public Map<String, Integer> computeTokenTypes(String[] tokenNames);

1016

1017

/** Using the map of token names to token types, return the type */

1018

public int getTokenType(String tokenName);

1019

1020

/** Walk entire tree and make a node name to nodes mapping.

1021

* For now, use recursion but later nonrecursive version may be

1022

* more efficient. This method can be used to prep for a way to

1023

* search a tree.

1024

*/

1025

public Map<Integer, List> index(Object t);

1026

1027

/** Return a List of tree nodes with token type ttype */

1028

public List find(Object t, int ttype);

1029

1030

/** Return a List of subtrees matching pattern */

1031

public List find(Object t, String pattern);

1032

1033

public Object findFirst(Object t, int ttype);

1034

public Object findFirst(Object t, String pattern);

1035

1036

/** Visit every ttype node in t, invoking the visitor. This is a quicker

1037

* version of the general visit(t, pattern) method. The labels arg

1038

* of the visitor action method is never set (it's null) since using

1039

* a token type rather than a pattern doesn't let us set a label.

1040

*/

1041

public void visit(Object t, int ttype, ContextVisitor visitor);

1042

1043

/** For all subtrees that match the pattern, execute the visit action.

1044

* The implementation uses the root node of the pattern in combination

1045

* with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.

1046

* Patterns with wildcard roots are also not allowed.

1047

*/

1048

public void visit(Object t, String pattern, ContextVisitor visitor);

1049

1050

/** Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels

1051

* on the various nodes and '.' (dot) as the node/subtree wildcard,

1052

* return true if the pattern matches and fill the labels Map with

1053

* the labels pointing at the appropriate nodes. Return false if

1054

* the pattern is malformed or the tree does not match.

1055

*

1056

* If a node specifies a text arg in pattern, that must match.

1057

* For example, (ASSIGN ID["x"] .) means the ID node must have

1058

* text "x" and structure (ASSIGN ID *). The second ID means that

1059

* the ID must have the text "x".

1060

*

1061

* TODO: what if we want to assign a node to a label? If #foo is

1062

* always root node, then %foo is the node w/o making it the root.

1063

* This is like return label and input/output arg.

1064

*

1065

* The general form is (#label:)? name[text]? ('(' child+ ')')?

1066

* where '.' is text and name is same as '.' except text.

1067

*/

1068

public boolean parse(Object t, String pattern, Map<String, Object> labels);

1069

public boolean parse(Object t, String pattern);

1070

1071

/** Create a tree or node from the indicated tree pattern that has

1072

* token names and label references

1073

*/

1074

public Object create(String pattern);

1075

1076

/** Compare t1 and t2; return true if token types/text, structure match exactly.

1077

* The trees are examined in their entirety so that (A B) does not match

1078

* (A B C) nor (A (B C)).

1079

*/

1080

public boolean equals(Object t1, Object t2, TreeAdaptor adaptor);

1081

public boolean equals(Object t1, Object t2);

1082

}

1083

```

1084

1085

### TreeVisitor

1086

1087

Utility for traversing trees with visitor pattern support.

1088

1089

```java { .api }

1090

/**

1091

* Tree traversal with visitor pattern

1092

*/

1093

public class TreeVisitor {

1094

protected TreeAdaptor adaptor;

1095

1096

public TreeVisitor(TreeAdaptor adaptor);

1097

public TreeVisitor();

1098

1099

/** Visit every node in tree t and trigger an action for each node

1100

* before/after having visited all of its children. Bottom up walk.

1101

* Execute an action for every node in the tree using a bottom/up walk.

1102

* Return same or modified tree structure.

1103

*

1104

* It returns Object because the user may change the root and even

1105

* the tree type. The invariant is that the return value is the new tree,

1106

* if any, that should take the place of this node.

1107

*

1108

* Note that the child list is altered by this method as it does its

1109

* work. Do not rely on the children list to be unmodified after this call.

1110

* Additionally, upon entry the current node's parent should be correct

1111

* in that this visitor may call setParent(). Make sure to call

1112

* freshenParentAndChildIndexes() before calling this method.

1113

*/

1114

public Object visit(Object t, TreeVisitorAction action);

1115

}

1116

```

1117

1118

### TreeVisitorAction

1119

1120

Interface for tree visitor actions.

1121

1122

```java { .api }

1123

/**

1124

* Interface for tree visitor actions

1125

*/

1126

public interface TreeVisitorAction {

1127

/** Execute an action before visiting children of t. Return t or

1128

* a rewritten t. It is up to the visitor to decide what to do

1129

* with the return value. Children of returned value will be

1130

* visited if using TreeVisitor.visit().

1131

*/

1132

public Object pre(Object t);

1133

1134

/** Execute an action after visiting children of t. Return t or

1135

* a rewritten t. It is up to the visitor to decide what to do

1136

* with the return value.

1137

*/

1138

public Object post(Object t);

1139

}

1140

```

1141

1142

### TreeIterator

1143

1144

Iterator for traversing tree nodes in document order.

1145

1146

```java { .api }

1147

/**

1148

* Iterator for tree traversal

1149

*/

1150

public class TreeIterator implements Iterator<Object> {

1151

protected TreeAdaptor adaptor;

1152

protected Object root;

1153

protected Object tree;

1154

protected boolean firstTime;

1155

1156

public TreeIterator(CommonTree tree);

1157

public TreeIterator(TreeAdaptor adaptor, Object tree);

1158

1159

public void reset();

1160

public boolean hasNext();

1161

public Object next();

1162

public void remove() throws UnsupportedOperationException;

1163

}

1164

```

1165

1166

**Tree Utility Usage Examples:**

1167

1168

```java

1169

import org.antlr.runtime.tree.*;

1170

import org.antlr.runtime.*;

1171

1172

// TreeWizard examples

1173

String[] tokenNames = {"PLUS", "MULT", "ID", "INT"};

1174

TreeWizard wiz = new TreeWizard(adaptor, tokenNames);

1175

1176

// Find all nodes of a specific type

1177

List<Object> plusNodes = wiz.find(tree, wiz.getTokenType("PLUS"));

1178

1179

// Find nodes matching a pattern

1180

List<Object> assignments = wiz.find(tree, "(ASSIGN %lhs:ID %rhs:.)");

1181

1182

// Parse and extract labeled nodes

1183

Map<String, Object> labels = new HashMap<String, Object>();

1184

if (wiz.parse(tree, "(ASSIGN %lhs:ID %rhs:.)", labels)) {

1185

Object lhs = labels.get("lhs");

1186

Object rhs = labels.get("rhs");

1187

System.out.println("Assignment: " + adaptor.getText(lhs) + " = " + adaptor.getText(rhs));

1188

}

1189

1190

// Create tree from pattern

1191

Object newTree = wiz.create("(PLUS ID[\"x\"] INT[\"42\"])");

1192

1193

// Visit all nodes of a type

1194

wiz.visit(tree, wiz.getTokenType("ID"), new TreeWizard.Visitor() {

1195

public void visit(Object t) {

1196

System.out.println("Found identifier: " + adaptor.getText(t));

1197

}

1198

});

1199

1200

// TreeVisitor examples

1201

TreeVisitor visitor = new TreeVisitor(adaptor);

1202

1203

// Visit tree with custom action

1204

Object newTree = visitor.visit(tree, new TreeVisitorAction() {

1205

public Object pre(Object t) {

1206

System.out.println("Entering: " + adaptor.getText(t));

1207

return t; // Continue with original node

1208

}

1209

1210

public Object post(Object t) {

1211

System.out.println("Leaving: " + adaptor.getText(t));

1212

1213

// Example: replace all ID nodes with IDENTIFIER nodes

1214

if (adaptor.getType(t) == MyParser.ID) {

1215

Object newNode = adaptor.create(MyParser.IDENTIFIER, adaptor.getText(t));

1216

return newNode;

1217

}

1218

return t;

1219

}

1220

});

1221

1222

// TreeIterator examples

1223

TreeIterator iter = new TreeIterator(adaptor, tree);

1224

while (iter.hasNext()) {

1225

Object node = iter.next();

1226

System.out.println("Node: " + adaptor.getText(node));

1227

}

1228

```