I split the tree interface into multiple simpler ones and removed the methods that can modify a node. Either you should use the adapter or, you know the concrete type and then you can call those methods directly not through the interface. The whole point of the interface is to be flexible but then for consistency users must use the adapters. I'm also starting to pull helper methods into a Trees "module". I also renamed CommonTree to be CommonAST. I also renamed the adapters appropriately.

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9040]
This commit is contained in:
parrt 2011-09-04 12:02:07 -08:00
parent 783f1bc38f
commit 32a375bbf7
36 changed files with 440 additions and 362 deletions

View File

@ -100,10 +100,10 @@ public class CommonToken implements WritableToken, Serializable {
if ( text!=null ) {
return text;
}
CharStream input = getTokenSource().getInputStream();
if ( input==null ) {
return null;
}
TokenSource tokens = getTokenSource();
if ( tokens==null ) return null;
CharStream input = tokens.getInputStream();
if ( input==null ) return null;
int n = input.size();
if ( start<n && stop<n) {
return input.substring(start,stop);

View File

@ -55,8 +55,10 @@ public class LexerRecognitionExeption extends RuntimeException {
this.lexer = lexer;
this.index = input.index();
this.c = input.LA(1);
this.line = lexer.getLine();
this.charPositionInLine = lexer.getCharPositionInLine();
if ( lexer!=null ) {
this.line = lexer.getLine();
this.charPositionInLine = lexer.getCharPositionInLine();
}
}
}

View File

@ -36,7 +36,7 @@ import org.antlr.v4.runtime.tree.*;
*/
public class Parser extends BaseRecognizer {
public TreeAdaptor _adaptor = new CommonTreeAdaptor();
public ASTAdaptor _adaptor = new CommonASTAdaptor();
public Parser(TokenStream input) {
super(input);

View File

@ -187,7 +187,7 @@ public class RecognitionException extends RuntimeException {
}
else if ( recognizer._input instanceof TreeNodeStream) {
TreeNodeStream nodes = (TreeNodeStream)recognizer._input;
TreeAdaptor adaptor = nodes.getTreeAdaptor();
ASTAdaptor adaptor = nodes.getTreeAdaptor();
return adaptor.getType(node);
}
else {

View File

@ -29,7 +29,8 @@
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.*;
import java.util.*;
@ -262,10 +263,21 @@ public class RuleContext implements ParseTree.RuleNode {
public ParseTree getParent() { return parent; }
public Object getPayload() { return this; }
public RuleContext getPayload() { return this; }
public int getChildCount() { return children!=null ? children.size() : 0; }
public Interval getSourceInterval() {
if ( getChildCount()==0 ) return Interval.ZeroLength;
int start = getChild(0).getSourceInterval().a;
int stop = getChild(getChildCount()-1).getSourceInterval().b;
return new Interval(start, stop);
}
public String toStringTree() {
return Trees.toStringTree(this);
}
public String toString() {
return toString(null);
}

View File

@ -277,9 +277,9 @@ public interface DebugEventListener {
/** Make a node the new root of an existing root. See
*
* Note: the newRootID parameter is possibly different
* than the TreeAdaptor.becomeRoot() newRoot parameter.
* than the ASTAdaptor.becomeRoot() newRoot parameter.
* In our case, it will always be the result of calling
* TreeAdaptor.becomeRoot() and not root_n or whatever.
* ASTAdaptor.becomeRoot() and not root_n or whatever.
*
* The listener should assume that this event occurs
* only when the current subrule (or rule) subtree is
@ -288,7 +288,7 @@ public interface DebugEventListener {
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only IDs are set.
*
* @see org.antlr.v4.runtime.tree.TreeAdaptor becomeRoot()
* @see org.antlr.v4.runtime.tree.ASTAdaptor becomeRoot()
*/
public void becomeRoot(Object newRoot, Object oldRoot);
@ -297,7 +297,7 @@ public interface DebugEventListener {
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only IDs are set.
*
* @see org.antlr.v4.runtime.tree.TreeAdaptor addChild()
* @see org.antlr.v4.runtime.tree.ASTAdaptor addChild()
*/
public void addChild(Object root, Object child);

View File

@ -28,7 +28,7 @@
package org.antlr.v4.runtime.debug;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.TreeAdaptor;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import java.io.*;
import java.net.*;
@ -55,13 +55,13 @@ public class DebugEventSocketProxy extends BlankDebugEventListener {
* we don't know how to cast it (Parser or TreeParser) to get
* the adaptor field. Must be set with a constructor. :(
*/
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
public DebugEventSocketProxy(BaseRecognizer recognizer, TreeAdaptor adaptor) {
public DebugEventSocketProxy(BaseRecognizer recognizer, ASTAdaptor adaptor) {
this(recognizer, DEFAULT_DEBUGGER_PORT, adaptor);
}
public DebugEventSocketProxy(BaseRecognizer recognizer, int port, TreeAdaptor adaptor) {
public DebugEventSocketProxy(BaseRecognizer recognizer, int port, ASTAdaptor adaptor) {
this.grammarFileName = recognizer.getGrammarFileName();
this.adaptor = adaptor;
this.port = port;
@ -316,8 +316,8 @@ public class DebugEventSocketProxy extends BlankDebugEventListener {
// support
public void setTreeAdaptor(TreeAdaptor adaptor) { this.adaptor = adaptor; }
public TreeAdaptor getTreeAdaptor() { return adaptor; }
public void setTreeAdaptor(ASTAdaptor adaptor) { this.adaptor = adaptor; }
public ASTAdaptor getTreeAdaptor() { return adaptor; }
protected String serializeToken(Token t) {
StringBuffer buf = new StringBuffer(50);

View File

@ -27,15 +27,13 @@
*/
package org.antlr.v4.runtime.debug;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.TreeAdaptor;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import java.util.List;
/** A TreeAdaptor proxy that fires debugging events to a DebugEventListener
* delegate and uses the TreeAdaptor delegate to do the actual work. All
/** An ASTAdaptor proxy that fires debugging events to a DebugEventListener
* delegate and uses the ASTAdaptor delegate to do the actual work. All
* AST events are triggered by this adaptor; no code gen changes are needed
* in generated rules. Debugging events are triggered *after* invoking
* tree adaptor routines.
@ -46,11 +44,11 @@ import java.util.List;
* not see a createNode event. A single <unknown> node is sufficient even
* if it represents a whole tree.
*/
public class DebugTreeAdaptor implements TreeAdaptor {
public class DebugTreeAdaptor implements ASTAdaptor {
protected DebugEventListener dbg;
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
public DebugTreeAdaptor(DebugEventListener dbg, TreeAdaptor adaptor) {
public DebugTreeAdaptor(DebugEventListener dbg, ASTAdaptor adaptor) {
this.dbg = dbg;
this.adaptor = adaptor;
}
@ -250,7 +248,7 @@ public class DebugTreeAdaptor implements TreeAdaptor {
this.dbg = dbg;
}
public TreeAdaptor getTreeAdaptor() {
public ASTAdaptor getTreeAdaptor() {
return adaptor;
}
}

View File

@ -36,7 +36,7 @@ import org.antlr.v4.runtime.tree.*;
*/
public class DebugTreeNodeStream implements TreeNodeStream {
protected DebugEventListener dbg;
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
protected TreeNodeStream input;
protected boolean initialStreamState = true;
@ -56,7 +56,7 @@ public class DebugTreeNodeStream implements TreeNodeStream {
this.dbg = dbg;
}
public TreeAdaptor getTreeAdaptor() {
public ASTAdaptor getTreeAdaptor() {
return adaptor;
}

View File

@ -28,7 +28,8 @@
package org.antlr.v4.runtime.debug;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.BaseAST;
import java.io.*;
import java.net.*;
@ -118,7 +119,7 @@ public class RemoteDebugEventSocketListener implements Runnable {
}
}
public static class ProxyTree extends BaseTree {
public static class ProxyTree extends BaseAST {
public int ID;
public int type;
public int line = 0;
@ -137,11 +138,21 @@ public class RemoteDebugEventSocketListener implements Runnable {
public ProxyTree(int ID) { this.ID = ID; }
public int getTokenStartIndex() { return tokenIndex; }
public void setTokenStartIndex(int index) { }
public int getTokenStopIndex() { return 0; }
public void setTokenStopIndex(int index) { }
public Tree dupNode() { return null; }
public int getCharPositionInLine() {
return charPos;
}
public Token getPayload() {
return null;
}
public int getLine() {
return line;
}
public Interval getSourceInterval() {
return new Interval(tokenIndex, tokenIndex);
}
public int getType() { return type; }
public String getText() { return text; }
public String toString() {

View File

@ -28,13 +28,13 @@
package org.antlr.v4.runtime.debug;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TreeAdaptor;
import org.antlr.v4.runtime.tree.ASTAdaptor;
/** Print out (most of) the events... Useful for debugging, testing... */
public class TraceDebugEventListener extends BlankDebugEventListener {
TreeAdaptor adaptor;
ASTAdaptor adaptor;
public TraceDebugEventListener(TreeAdaptor adaptor) {
public TraceDebugEventListener(ASTAdaptor adaptor) {
this.adaptor = adaptor;
}

View File

@ -32,6 +32,8 @@ package org.antlr.v4.runtime.misc;
public class Interval {
public static final int INTERVAL_POOL_MAX_VALUE = 1000;
public static final Interval ZeroLength = new Interval(0,-1);
static Interval[] cache = new Interval[INTERVAL_POOL_MAX_VALUE+1];
public int a;

View File

@ -0,0 +1,77 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.Token;
import java.util.List;
/** An abstract syntax tree built by ANTLR during a parcel or tree parse. */
public interface AST extends SyntaxTree {
/** Is there is a node above with token type ttype? */
public boolean hasAncestor(int ttype);
/** Walk upwards and get first ancestor with this token type. */
public AST getAncestor(int ttype);
/** Return a list of all ancestors of this node. The first node of
* list is the root and the last is the parent of this node.
*/
public List getAncestors();
/** This node is what child index? 0..n-1 */
public int getChildIndex();
/** Set the parent and child index values for all children */
public void freshenParentAndChildIndexes();
/** Indicates the node is a nil node but may still have children, meaning
* the tree is a flat list.
*/
boolean isNil();
/** Return a token type; needed for tree parsing */
int getType();
/** Text for this node alone, not the subtree */
String getText();
// TODO: do we need line/charpos????
/** In case we don't have a token payload, what is the line for errors? */
int getLine();
int getCharPositionInLine();
/** Redefined from Tree interface so we can narrow the return type */
AST getParent();
/** Redefined from Tree interface so we can narrow the return type */
Token getPayload();
}

View File

@ -36,13 +36,10 @@ import java.util.List;
/** How to create and navigate trees. Rather than have a separate factory
* and adaptor, I've merged them. Makes sense to encapsulate.
*
* This takes the place of the tree construction code generated in the
* generated code in 2.x and the ASTFactory.
*
* I do not need to know the type of a tree at all so they are all
* generic Objects. This may increase the amount of typecasting needed. :(
* generic Objects.
*/
public interface TreeAdaptor {
public interface ASTAdaptor {
// BEGIN new v4 stuff
// If not null root, add kids to it
@ -57,7 +54,7 @@ public interface TreeAdaptor {
// C o n s t r u c t i o n
/** Create a tree node from Token object; for CommonTree type trees,
/** Create a tree node from Token object; for CommonAST type trees,
* then the token just becomes the payload. This is the most
* common create call.
*
@ -170,7 +167,7 @@ public interface TreeAdaptor {
* Be advised: when debugging ASTs, the DebugTreeAdaptor manually
* calls create(Token child) and then plain becomeRoot(node, node)
* because it needs to trap calls to create, but it can't since it delegates
* to not inherits from the TreeAdaptor.
* to not inherits from the ASTAdaptor.
*/
public Object becomeRoot(Token newRoot, Object oldRoot);

View File

@ -37,24 +37,30 @@ import java.util.*;
* an empty node whose children represent the list. An empty, but
* non-null node is called "nil".
*/
public abstract class BaseTree implements Tree {
protected List children;
public abstract class BaseAST implements AST {
/** Who is the parent node of this node; if null, implies node is root */
public BaseAST parent;
public BaseTree() {
protected List<BaseAST> children;
/** What index is this node in the child list? Range: 0..n-1 */
public int childIndex = -1;
public BaseAST() {
}
/** Create a new node from an existing node does nothing for BaseTree
* as there are no fields other than the children list, which cannot
* be copied as the children are not considered part of this node.
*/
public BaseTree(Tree node) {
public BaseAST(AST node) {
}
public Tree getChild(int i) {
public BaseAST getChild(int i) {
if ( children==null || i>=children.size() ) {
return null;
}
return (Tree)children.get(i);
return children.get(i);
}
/** Get the children internal List; note that if you directly mess with
@ -64,9 +70,9 @@ public abstract class BaseTree implements Tree {
return children;
}
public Tree getFirstChildWithType(int type) {
public AST getFirstChildWithType(int type) {
for (int i = 0; children!=null && i < children.size(); i++) {
Tree t = (Tree) children.get(i);
AST t = (AST) children.get(i);
if ( t.getType()==type ) {
return t;
}
@ -87,13 +93,13 @@ public abstract class BaseTree implements Tree {
* and child isNil then this routine moves children to t via
* t.children = child.children; i.e., without copying the array.
*/
public void addChild(Tree t) {
public void addChild(BaseAST t) {
//System.out.println("add child "+t.toStringTree()+" "+this.toStringTree());
//System.out.println("existing children: "+children);
if ( t==null ) {
return; // do nothing upon addChild(null)
}
BaseTree childTree = (BaseTree)t;
BaseAST childTree = (BaseAST)t;
if ( childTree.isNil() ) { // t is an empty node possibly with children
if ( this.children!=null && this.children == childTree.children ) {
throw new RuntimeException("attempt to add child list to itself");
@ -103,7 +109,7 @@ public abstract class BaseTree implements Tree {
if ( this.children!=null ) { // must copy, this has children already
int n = childTree.children.size();
for (int i = 0; i < n; i++) {
Tree c = (Tree)childTree.children.get(i);
BaseAST c = childTree.children.get(i);
this.children.add(c);
// handle double-link stuff for each child of nil root
c.setParent(this);
@ -130,19 +136,19 @@ public abstract class BaseTree implements Tree {
}
/** Add all elements of kids list as children of this node */
public void addChildren(List kids) {
public void addChildren(List<BaseAST> kids) {
if ( kids==null ) return;
for (int i = 0; i < kids.size(); i++) {
Tree t = (Tree) kids.get(i);
BaseAST t = kids.get(i);
addChild(t);
}
}
public void setChild(int i, Tree t) {
public void setChild(int i, BaseAST t) {
if ( t==null ) {
return;
}
if ( t.isNil() ) {
if ( ((AST)t).isNil() ) {
throw new IllegalArgumentException("Can't set single child to a list");
}
if ( children==null ) {
@ -153,17 +159,33 @@ public abstract class BaseTree implements Tree {
t.setChildIndex(i);
}
public int getChildIndex() {
return childIndex;
}
public AST getParent() {
return parent;
}
public void setParent(BaseAST t) {
this.parent = t;
}
public void setChildIndex(int index) {
this.childIndex = index;
}
public Object deleteChild(int i) {
if ( children==null ) {
return null;
}
Tree killed = (Tree)children.remove(i);
AST killed = (AST)children.remove(i);
// walk rest and decrement their child indexes
this.freshenParentAndChildIndexes(i);
return killed;
}
public boolean deleteChild(Tree t) {
public boolean deleteChild(AST t) {
for (int i=0; i<children.size(); i++) {
Object c = children.get(i);
if ( c == t ) {
@ -178,7 +200,7 @@ public abstract class BaseTree implements Tree {
i+1..n-1 to the right one position. Set parent / indexes properly
but does NOT collapse nil-rooted t's that come in here like addChild.
*/
public void insertChild(int i, Object t) {
public void insertChild(int i, BaseAST t) {
if (i < 0 || i >= getChildCount()) {
throw new IndexOutOfBoundsException(i+" out or range");
}
@ -205,8 +227,8 @@ public abstract class BaseTree implements Tree {
}
int replacingHowMany = stopChildIndex - startChildIndex + 1;
int replacingWithHowMany;
BaseTree newTree = (BaseTree)t;
List newChildren = null;
BaseAST newTree = (BaseAST)t;
List<BaseAST> newChildren = null;
// normalize to a list of children to add: newChildren
if ( newTree.isNil() ) {
newChildren = newTree.children;
@ -222,7 +244,7 @@ public abstract class BaseTree implements Tree {
if ( delta == 0 ) {
int j = 0; // index into new children
for (int i=startChildIndex; i<=stopChildIndex; i++) {
BaseTree child = (BaseTree)newChildren.get(j);
BaseAST child = (BaseAST)newChildren.get(j);
children.set(i, child);
child.setParent(this);
child.setChildIndex(i);
@ -272,7 +294,7 @@ public abstract class BaseTree implements Tree {
public void freshenParentAndChildIndexes(int offset) {
int n = getChildCount();
for (int c = offset; c < n; c++) {
Tree child = (Tree)getChild(c);
BaseAST child = getChild(c);
child.setChildIndex(c);
child.setParent(this);
}
@ -285,7 +307,7 @@ public abstract class BaseTree implements Tree {
public void freshenParentAndChildIndexesDeeply(int offset) {
int n = getChildCount();
for (int c = offset; c < n; c++) {
BaseTree child = (BaseTree)getChild(c);
BaseAST child = (BaseAST)getChild(c);
child.setChildIndex(c);
child.setParent(this);
child.freshenParentAndChildIndexesDeeply();
@ -296,7 +318,7 @@ public abstract class BaseTree implements Tree {
sanityCheckParentAndChildIndexes(null, -1);
}
public void sanityCheckParentAndChildIndexes(Tree parent, int i) {
public void sanityCheckParentAndChildIndexes(AST parent, int i) {
if ( parent!=this.getParent() ) {
throw new IllegalStateException("parents don't match; expected "+parent+" found "+this.getParent());
}
@ -305,32 +327,17 @@ public abstract class BaseTree implements Tree {
}
int n = this.getChildCount();
for (int c = 0; c < n; c++) {
CommonTree child = (CommonTree)this.getChild(c);
CommonAST child = (CommonAST)this.getChild(c);
child.sanityCheckParentAndChildIndexes(this, c);
}
}
/** BaseTree doesn't track child indexes. */
public int getChildIndex() {
return 0;
}
public void setChildIndex(int index) {
}
/** BaseTree doesn't track parent pointers. */
public Tree getParent() {
return null;
}
public void setParent(Tree t) {
}
/** Walk upwards looking for ancestor with this token type. */
public boolean hasAncestor(int ttype) { return getAncestor(ttype)!=null; }
/** Walk upwards and get first ancestor with this token type. */
public Tree getAncestor(int ttype) {
Tree t = this;
public AST getAncestor(int ttype) {
AST t = this;
t = t.getParent();
while ( t!=null ) {
if ( t.getType()==ttype ) return t;
@ -344,8 +351,8 @@ public abstract class BaseTree implements Tree {
*/
public List getAncestors() {
if ( getParent()==null ) return null;
List ancestors = new ArrayList();
Tree t = this;
List<AST> ancestors = new ArrayList();
AST t = this;
t = t.getParent();
while ( t!=null ) {
ancestors.add(0, t); // insert at start
@ -354,7 +361,9 @@ public abstract class BaseTree implements Tree {
return ancestors;
}
/** Print out a whole tree not just a node */
/** Don't use standard tree printing mechanism since ASTs can have nil
* root nodes.
*/
public String toStringTree() {
if ( children==null || children.size()==0 ) {
return this.toString();
@ -366,7 +375,7 @@ public abstract class BaseTree implements Tree {
buf.append(' ');
}
for (int i = 0; children!=null && i < children.size(); i++) {
Tree t = (Tree)children.get(i);
AST t = children.get(i);
if ( i>0 ) {
buf.append(' ');
}
@ -377,15 +386,4 @@ public abstract class BaseTree implements Tree {
}
return buf.toString();
}
public int getLine() {
return 0;
}
public int getCharPositionInLine() {
return 0;
}
/** Override to say how a node (not a tree) should look as text */
public abstract String toString();
}

View File

@ -33,25 +33,16 @@ import org.antlr.v4.runtime.*;
import java.util.*;
/** A TreeAdaptor that works with any Tree implementation. */
public abstract class BaseTreeAdaptor implements TreeAdaptor {
/** An ASTAdaptor that works with any BaseAST implementation. */
public abstract class BaseASTAdaptor implements ASTAdaptor {
/** System.identityHashCode() is not always unique; we have to
* track ourselves. That's ok, it's only for debugging, though it's
* expensive: we have to create a hashtable with all tree nodes in it.
* TODO: rm?
*/
protected Map treeToUniqueIDMap;
protected Map<BaseAST, Integer> treeToUniqueIDMap;
protected int uniqueNodeID = 1;
// BEGIN v4 stuff
/* not needed
public void addChildren(Object root, List kids) {
if ( root!=null ) ((Tree)root).addChildren(kids);
}
public List getChildren(Object root) { return ((Tree)root).getChildren(); }
*/
public List<Object> createElementList() {
return new ElementList<Object>(this);
}
@ -66,7 +57,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
* with an error.
*
* If you specify your own kind of tree nodes, you will likely have to
* override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
* override this method. CommonAST returns Token.INVALID_TOKEN_TYPE
* if no token payload but you might have to set token type for diff
* node type.
*
@ -82,7 +73,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
}
public boolean isNil(Object tree) {
return ((Tree)tree).isNil();
return ((AST)tree).isNil();
}
public Object dupTree(Object tree) {
@ -90,7 +81,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
}
/** This is generic in the sense that it will work with any kind of
* tree (not just Tree interface). It invokes the adaptor routines
* tree (not just AST interface). It invokes the adaptor routines
* not the tree node routines to do the construction.
*/
public Object dupTree(Object t, Object parent) {
@ -119,7 +110,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
*/
public void addChild(Object t, Object child) {
if ( t!=null && child!=null ) {
((Tree)t).addChild((Tree)child);
((BaseAST)t).addChild((BaseAST) child);
}
}
@ -151,15 +142,15 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
*/
public Object becomeRoot(Object newRoot, Object oldRoot) {
//System.out.println("becomeroot new "+newRoot.toString()+" old "+oldRoot);
Tree newRootTree = (Tree)newRoot;
Tree oldRootTree = (Tree)oldRoot;
BaseAST newRootTree = (BaseAST)newRoot;
BaseAST oldRootTree = (BaseAST)oldRoot;
if ( oldRoot==null ) {
return newRoot;
}
// handle ^(nil real-node)
if ( newRootTree.isNil() ) {
int nc = newRootTree.getChildCount();
if ( nc==1 ) newRootTree = (Tree)newRootTree.getChild(0);
if ( nc==1 ) newRootTree = newRootTree.getChild(0);
else if ( nc >1 ) {
// TODO: make tree run time exceptions hierarchy
throw new RuntimeException("more than one node as root (TODO: make exception hierarchy)");
@ -174,14 +165,14 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
/** Transform ^(nil x) to x and nil to null */
public Object rulePostProcessing(Object root) {
//System.out.println("rulePostProcessing: "+((Tree)root).toStringTree());
Tree r = (Tree)root;
//System.out.println("rulePostProcessing: "+((AST)root).toStringTree());
BaseAST r = (BaseAST)root;
if ( r!=null && r.isNil() ) {
if ( r.getChildCount()==0 ) {
r = null;
}
else if ( r.getChildCount()==1 ) {
r = (Tree)r.getChild(0);
r = r.getChild(0);
// whoever invokes rule will set parent and child index
r.setParent(null);
r.setChildIndex(-1);
@ -198,7 +189,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
WritableToken tok = createToken(fromToken);
//((ClassicToken)fromToken).setType(tokenType);
tok.setType(tokenType);
Tree t = (Tree)create(tok);
AST t = (AST)create(tok);
return t;
}
@ -207,46 +198,46 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
WritableToken tok = createToken(fromToken);
tok.setType(tokenType);
tok.setText(text);
Tree t = (Tree)create(tok);
AST t = (AST)create(tok);
return t;
}
public Object create(int tokenType, String text) {
Token fromToken = createToken(tokenType, text);
Tree t = (Tree)create(fromToken);
AST t = (AST)create(fromToken);
return t;
}
public int getType(Object t) {
return ((Tree)t).getType();
return ((AST)t).getType();
}
public void setType(Object t, int type) {
throw new NoSuchMethodError("don't know enough about Tree node");
throw new NoSuchMethodError("don't know enough about AST node");
}
public String getText(Object t) {
return ((Tree)t).getText();
return ((AST)t).getText();
}
public void setText(Object t, String text) {
throw new NoSuchMethodError("don't know enough about Tree node");
throw new NoSuchMethodError("don't know enough about AST node");
}
public Object getChild(Object t, int i) {
return ((Tree)t).getChild(i);
return ((AST)t).getChild(i);
}
public void setChild(Object t, int i, Object child) {
((Tree)t).setChild(i, (Tree)child);
((BaseAST)t).setChild(i, (BaseAST)child);
}
public Object deleteChild(Object t, int i) {
return ((Tree)t).deleteChild(i);
return ((BaseAST)t).deleteChild(i);
}
public int getChildCount(Object t) {
return ((Tree)t).getChildCount();
return ((BaseAST)t).getChildCount();
}
public int getUniqueID(Object node) {
@ -255,10 +246,10 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
}
Integer prevID = (Integer)treeToUniqueIDMap.get(node);
if ( prevID!=null ) {
return prevID.intValue();
return prevID;
}
int ID = uniqueNodeID;
treeToUniqueIDMap.put(node, new Integer(ID));
treeToUniqueIDMap.put((BaseAST)node, ID);
uniqueNodeID++;
return ID;
// GC makes these nonunique:

View File

@ -30,17 +30,13 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.gui.ASTViewer;
import java.util.Set;
/** A tree node that is wrapper for a Token object. After 3.0 release
* while building tree rewrite stuff, it became clear that computing
* parent and child index is very difficult and cumbersome. Better to
* spend the space in every tree node. If you don't want these extra
* fields, it's easy to cut them out in your own BaseTree subclass.
*/
public class CommonTree extends BaseTree {
/** A tree node that is wrapper for a Token object. */
public class CommonAST extends BaseAST {
/** A single token is the payload */
public Token token;
@ -49,22 +45,16 @@ public class CommonTree extends BaseTree {
*/
protected int startIndex=-1, stopIndex=-1;
/** Who is the parent node of this node; if null, implies node is root */
public CommonTree parent;
public CommonAST() { }
/** What index is this node in the child list? Range: 0..n-1 */
public int childIndex = -1;
public CommonTree() { }
public CommonTree(CommonTree node) {
public CommonAST(CommonAST node) {
super(node);
this.token = node.token;
this.startIndex = node.startIndex;
this.stopIndex = node.stopIndex;
}
public CommonTree(Token t) {
public CommonAST(Token t) {
this.token = t;
}
@ -72,8 +62,12 @@ public class CommonTree extends BaseTree {
return token;
}
public Tree dupNode() {
return new CommonTree(this);
public Token getPayload() {
return getToken();
}
public Interval getSourceInterval() {
return new Interval(getTokenStartIndex(), getTokenStopIndex());
}
public boolean isNil() {
@ -148,33 +142,17 @@ public class CommonTree extends BaseTree {
return;
}
for (int i=0; i<children.size(); i++) {
((CommonTree)children.get(i)).setUnknownTokenBoundaries();
((CommonAST)children.get(i)).setUnknownTokenBoundaries();
}
if ( startIndex>=0 && stopIndex>=0 ) return; // already set
if ( children.size() > 0 ) {
CommonTree firstChild = (CommonTree)children.get(0);
CommonTree lastChild = (CommonTree)children.get(children.size()-1);
CommonAST firstChild = (CommonAST)children.get(0);
CommonAST lastChild = (CommonAST)children.get(children.size()-1);
startIndex = firstChild.getTokenStartIndex();
stopIndex = lastChild.getTokenStopIndex();
}
}
public int getChildIndex() {
return childIndex;
}
public Tree getParent() {
return parent;
}
public void setParent(Tree t) {
this.parent = (CommonTree)t;
}
public void setChildIndex(int index) {
this.childIndex = index;
}
// TODO: move to basetree when i settle on how runtime works
public void inspect() {
ASTViewer viewer = new ASTViewer(this);
@ -184,26 +162,26 @@ public class CommonTree extends BaseTree {
// TODO: move to basetree when i settle on how runtime works
// TODO: don't include this node!!
// TODO: reuse other method
public CommonTree getFirstDescendantWithType(int type) {
public CommonAST getFirstDescendantWithType(int type) {
if ( getType()==type ) return this;
if ( children==null ) return null;
for (Object c : children) {
CommonTree t = (CommonTree)c;
CommonAST t = (CommonAST)c;
if ( t.getType()==type ) return t;
CommonTree d = t.getFirstDescendantWithType(type);
CommonAST d = t.getFirstDescendantWithType(type);
if ( d!=null ) return d;
}
return null;
}
// TODO: don't include this node!!
public CommonTree getFirstDescendantWithType(Set<Integer> types) {
public CommonAST getFirstDescendantWithType(Set<Integer> types) {
if ( types.contains(getType()) ) return this;
if ( children==null ) return null;
for (Object c : children) {
CommonTree t = (CommonTree)c;
CommonAST t = (CommonAST)c;
if ( types.contains(t.getType()) ) return t;
CommonTree d = t.getFirstDescendantWithType(types);
CommonAST d = t.getFirstDescendantWithType(types);
if ( d!=null ) return d;
}
return null;

View File

@ -31,17 +31,16 @@ package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
/** A TreeAdaptor that works with any Tree implementation. It provides
/** An ASTAdaptor that works with CommonAST. It provides
* really just factory methods; all the work is done by BaseTreeAdaptor.
* If you would like to have different tokens created than ClassicToken
* If you would like to have different tokens created than CommonToken
* objects, you need to override this and then set the parser tree adaptor to
* use your subclass.
*
* To get your parser to build nodes of a different type, override
* create(Token), errorNode(), and to be safe, YourTreeClass.dupNode().
* dupNode is called to duplicate nodes during rewrite operations.
* create(Token), errorNode().
*/
public class CommonTreeAdaptor extends BaseTreeAdaptor {
public class CommonASTAdaptor extends BaseASTAdaptor {
/** Duplicate a node. This is part of the factory;
* override if you want another kind of node to be built.
*
@ -50,11 +49,12 @@ public class CommonTreeAdaptor extends BaseTreeAdaptor {
*/
public Object dupNode(Object t) {
if ( t==null ) return null;
return ((Tree)t).dupNode();
return new CommonAST((CommonAST)t);
// return ((Tree)t).dupNode();
}
public Object create(Token payload) {
return new CommonTree(payload);
return new CommonAST(payload);
}
/** Tell me how to create a token for use with imaginary token nodes.
@ -90,7 +90,7 @@ public class CommonTreeAdaptor extends BaseTreeAdaptor {
}
/** Track start/stop token for subtree root created for a rule.
* Only works with Tree nodes. For rules that match nothing,
* Only works with CommonAST nodes. For rules that match nothing,
* seems like this will yield start=i and stop=i-1 in a nil node.
* Might be useful info so I'll not force to be i..i.
*/
@ -100,72 +100,72 @@ public class CommonTreeAdaptor extends BaseTreeAdaptor {
int stop = 0;
if ( startToken!=null ) start = startToken.getTokenIndex();
if ( stopToken!=null ) stop = stopToken.getTokenIndex();
((Tree)t).setTokenStartIndex(start);
((Tree)t).setTokenStopIndex(stop);
((CommonAST)t).setTokenStartIndex(start);
((CommonAST)t).setTokenStopIndex(stop);
}
public int getTokenStartIndex(Object t) {
if ( t==null ) return -1;
return ((Tree)t).getTokenStartIndex();
return ((CommonAST)t).getTokenStartIndex();
}
public int getTokenStopIndex(Object t) {
if ( t==null ) return -1;
return ((Tree)t).getTokenStopIndex();
return ((CommonAST)t).getTokenStopIndex();
}
public String getText(Object t) {
if ( t==null ) return null;
return ((Tree)t).getText();
return ((CommonAST)t).getText();
}
public int getType(Object t) {
if ( t==null ) return Token.INVALID_TYPE;
return ((Tree)t).getType();
return ((CommonAST)t).getType();
}
/** What is the Token associated with this node? If
* you are not using CommonTree, then you must
* you are not using CommonAST, then you must
* override this in your own adaptor.
*/
public Token getToken(Object t) {
if ( t instanceof CommonTree ) {
return ((CommonTree)t).getToken();
if ( t instanceof CommonAST) {
return ((CommonAST)t).getToken();
}
return null; // no idea what to do
}
public Object getChild(Object t, int i) {
if ( t==null ) return null;
return ((Tree)t).getChild(i);
return ((CommonAST)t).getChild(i);
}
public int getChildCount(Object t) {
if ( t==null ) return 0;
return ((Tree)t).getChildCount();
return ((CommonAST)t).getChildCount();
}
public Object getParent(Object t) {
if ( t==null ) return null;
return ((Tree)t).getParent();
return ((CommonAST)t).getParent();
}
public void setParent(Object t, Object parent) {
if ( t!=null ) ((Tree)t).setParent((Tree)parent);
if ( t!=null ) ((CommonAST)t).setParent((CommonAST)parent);
}
public int getChildIndex(Object t) {
if ( t==null ) return 0;
return ((Tree)t).getChildIndex();
return ((CommonAST)t).getChildIndex();
}
public void setChildIndex(Object t, int index) {
if ( t!=null ) ((Tree)t).setChildIndex(index);
if ( t!=null ) ((CommonAST)t).setChildIndex(index);
}
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
if ( parent!=null ) {
((Tree)parent).replaceChildren(startChildIndex, stopChildIndex, t);
((CommonAST)parent).replaceChildren(startChildIndex, stopChildIndex, t);
}
}
}

View File

@ -32,7 +32,7 @@ package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
/** A node representing erroneous token range in token stream */
public class CommonErrorNode extends CommonTree {
public class CommonErrorNode extends CommonAST {
public IntStream input;
public Token start;
public Token stop;

View File

@ -45,7 +45,7 @@ public class CommonTreeNodeStream extends LookaheadStream<Object> implements Tre
protected TokenStream tokens;
/** What tree adaptor was used to build these trees */
TreeAdaptor adaptor;
ASTAdaptor adaptor;
/** The tree iterator we using */
protected TreeIterator it;
@ -60,10 +60,10 @@ public class CommonTreeNodeStream extends LookaheadStream<Object> implements Tre
protected int level = 0;
public CommonTreeNodeStream(Object tree) {
this(new CommonTreeAdaptor(), tree);
this(new CommonASTAdaptor(), tree);
}
public CommonTreeNodeStream(TreeAdaptor adaptor, Object tree) {
public CommonTreeNodeStream(ASTAdaptor adaptor, Object tree) {
this.root = tree;
this.adaptor = adaptor;
it = new TreeIterator(adaptor,root);
@ -109,9 +109,9 @@ public class CommonTreeNodeStream extends LookaheadStream<Object> implements Tre
public void setTokenStream(TokenStream tokens) { this.tokens = tokens; }
public TreeAdaptor getTreeAdaptor() { return adaptor; }
public ASTAdaptor getTreeAdaptor() { return adaptor; }
public void setTreeAdaptor(TreeAdaptor adaptor) { this.adaptor = adaptor; }
public void setTreeAdaptor(ASTAdaptor adaptor) { this.adaptor = adaptor; }
public Object get(int i) {
throw new UnsupportedOperationException("Absolute node indexes are meaningless in an unbuffered stream");

View File

@ -33,7 +33,7 @@ import java.util.*;
/** This list tracks elements to left of -> for use on right of -> */
public class ElementList<E> extends ArrayList<E> {
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
/** Once a node / subtree has been used in a stream, it must be dup'd
* from then on.
@ -76,7 +76,7 @@ public class ElementList<E> extends ArrayList<E> {
public void remove() { throw new UnsupportedOperationException(); }
}
public ElementList(TreeAdaptor adaptor) {
public ElementList(ASTAdaptor adaptor) {
this.adaptor = adaptor;
}

View File

@ -30,6 +30,7 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.Interval;
/** An interface to access the tree of RuleContext objects created
* during a parse that makes the data structure look like a simple parse tree.
@ -39,7 +40,7 @@ import org.antlr.v4.runtime.*;
* Unlike the common AST stuff in the runtime library, there is no such thing
* as a nil node. The payload is either a token or a context object.
*/
public interface ParseTree {
public interface ParseTree extends SyntaxTree {
public interface RuleNode extends ParseTree {
RuleContext getRuleContext();
}
@ -59,7 +60,12 @@ public interface ParseTree {
public ParseTree getParent() { return parent; }
public Object getPayload() { return token; }
public Token getPayload() { return token; }
public Interval getSourceInterval() {
if ( token==null ) return Interval.ZeroLength;
return new Interval(token.getTokenIndex(), token.getTokenIndex());
}
public int getChildCount() { return 0; }
@ -68,23 +74,9 @@ public interface ParseTree {
if ( token.getType() == Token.EOF ) return "<EOF>";
return token.getText();
}
public String toStringTree() {
return toString();
}
}
/** The parent of this node. If the return value is null, then this
* node is the root of the parse tree.
*/
ParseTree getParent();
/** This can be a Token representing a leaf node or a RuleContext
* object representing a rule invocation.
*/
Object getPayload();
/** If there are children, get the ith value indexed from 0. */
ParseTree getChild(int i);
/** How many children are there? If there is none, then this
* node represents a token match leaf node.
*/
int getChildCount();
}

View File

@ -0,0 +1,46 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.misc.Interval;
/** A tree that knows about an interval in a token stream
* is some kind of syntax tree.
*/
public interface SyntaxTree extends Tree {
/** Return an interval indicating the index in the TokenStream of
* the 1st and last token associated with this subtree. If this
* note choose to use a leaf, then the interval represents a single token.
*
* If source interval is unknown, this does not return null.
* It returns an interval of length 0.
*/
Interval getSourceInterval();
}

View File

@ -29,108 +29,32 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.Token;
import java.util.List;
/** What does a tree look like? ANTLR has a number of support classes
* such as CommonTreeNodeStream that work on these kinds of trees. You
* don't have to make your trees implement this interface, but if you do,
* you'll be able to use more support code.
*
* NOTE: When constructing trees, ANTLR can build any kind of tree; it can
* even use Token objects as trees if you add a child list to your tokens.
*
* This is a tree node without any payload; just navigation and factory stuff.
/** The basic notion of a tree has a parent, a payload, and a list of children.
* It is the most abstract interface for all the trees used by ANTLR.
*/
public interface Tree {
public static final Tree INVALID_NODE = new CommonTree(Token.INVALID_TOKEN);
/** The parent of this node. If the return value is null, then this
* node is the root of the tree.
*/
Tree getParent();
// BEGIN v4
void addChildren(List t);
List getChildren();
// END v4
/** This method returns whatever object represents the data at this note.
* For example, for parse trees, the payload can be a Token representing
* a leaf node or a RuleContext object representing a rule invocation.
* For abstract syntax trees (ASTs), this is a Token object.
*/
Object getPayload();
/** If there are children, get the ith value indexed from 0. */
Tree getChild(int i);
/** How many children are there? If there is none, then this
* node represents a leaf node.
*/
int getChildCount();
// Tree tracks parent and child index now > 3.0
public Tree getParent();
public void setParent(Tree t);
/** Is there is a node above with token type ttype? */
public boolean hasAncestor(int ttype);
/** Walk upwards and get first ancestor with this token type. */
public Tree getAncestor(int ttype);
/** Return a list of all ancestors of this node. The first node of
* list is the root and the last is the parent of this node.
*/
public List getAncestors();
/** This node is what child index? 0..n-1 */
public int getChildIndex();
public void setChildIndex(int index);
/** Set the parent and child index values for all children */
public void freshenParentAndChildIndexes();
/** Add t as a child to this node. If t is null, do nothing. If t
* is nil, add all children of t to this' children.
/** Print out a whole tree, not just a node, in LISP format
* (root child1 .. childN). Print just a node if this is a leaf.
*/
void addChild(Tree t);
/** Set ith child (0..n-1) to t; t must be non-null and non-nil node */
public void setChild(int i, Tree t);
public Object deleteChild(int i);
/** Delete children from start to stop and replace with t even if t is
* a list (nil-root tree). num of children can increase or decrease.
* For huge child lists, inserting children can force walking rest of
* children to set their childindex; could be slow.
*/
public void replaceChildren(int startChildIndex, int stopChildIndex, Object t);
/** Indicates the node is a nil node but may still have children, meaning
* the tree is a flat list.
*/
boolean isNil();
/** What is the smallest token index (indexing from 0) for this node
* and its children?
*/
int getTokenStartIndex();
void setTokenStartIndex(int index);
/** What is the largest token index (indexing from 0) for this node
* and its children?
*/
int getTokenStopIndex();
void setTokenStopIndex(int index);
Tree dupNode();
/** Return a token type; needed for tree parsing */
int getType();
String getText();
/** In case we don't have a token payload, what is the line for errors? */
int getLine();
int getCharPositionInLine();
String toStringTree();
String toString();
}

View File

@ -29,8 +29,7 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
/**
Cut-n-paste from material I'm not using in the book anymore (edit later
@ -82,11 +81,11 @@ public class TreeFilter extends TreeParser {
}
protected TokenStream originalTokenStream;
protected TreeAdaptor originalAdaptor;
protected ASTAdaptor originalAdaptor;
public TreeFilter(TreeNodeStream input) {
super(input);
originalAdaptor = (TreeAdaptor) input.getTreeAdaptor();
originalAdaptor = (ASTAdaptor) input.getTreeAdaptor();
originalTokenStream = input.getTokenStream();
}
@ -102,7 +101,7 @@ public class TreeFilter extends TreeParser {
}
public void downup(Object t) {
TreeVisitor v = new TreeVisitor(new CommonTreeAdaptor());
TreeVisitor v = new TreeVisitor(new CommonASTAdaptor());
TreeVisitorAction actions = new TreeVisitorAction() {
public Object pre(Object t) { applyOnce(t, topdown_fptr); return t; }
public Object post(Object t) { applyOnce(t, bottomup_fptr); return t; }

View File

@ -40,7 +40,7 @@ import java.util.Iterator;
* Emit navigation nodes (DOWN, UP, and EOF) to let show tree structure.
*/
public class TreeIterator implements Iterator {
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
protected Object root;
protected Object tree;
protected boolean firstTime = true;
@ -56,10 +56,10 @@ public class TreeIterator implements Iterator {
protected FastQueue nodes;
public TreeIterator(Object tree) {
this(new CommonTreeAdaptor(),tree);
this(new CommonASTAdaptor(),tree);
}
public TreeIterator(TreeAdaptor adaptor, Object tree) {
public TreeIterator(ASTAdaptor adaptor, Object tree) {
this.adaptor = adaptor;
this.tree = tree;
this.root = tree;

View File

@ -67,7 +67,7 @@ public interface TreeNodeStream extends IntStream {
/** What adaptor can tell me how to interpret/navigate nodes and
* trees. E.g., get text of a node.
*/
public TreeAdaptor getTreeAdaptor();
public ASTAdaptor getTreeAdaptor();
/** As we flatten the tree, we use UP, DOWN nodes to represent
* the tree structure. When debugging we need unique nodes

View File

@ -84,7 +84,7 @@ public class TreeParser extends BaseRecognizer {
{
String tokenText =
"<missing "+getTokenNames()[expectedTokenType]+">";
TreeAdaptor adaptor = ((TreeNodeStream)e.input).getTreeAdaptor();
ASTAdaptor adaptor = ((TreeNodeStream)e.input).getTreeAdaptor();
return adaptor.create(new CommonToken(expectedTokenType, tokenText));
}
@ -144,7 +144,7 @@ public class TreeParser extends BaseRecognizer {
*/
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
if ( this instanceof TreeParser ) {
TreeAdaptor adaptor = ((TreeNodeStream)e.input).getTreeAdaptor();
ASTAdaptor adaptor = ((TreeNodeStream)e.input).getTreeAdaptor();
e.token = adaptor.getToken(e.node);
if ( e.token==null ) { // could be an UP/DOWN node
e.token = new CommonToken(adaptor.getType(e.node),
@ -171,7 +171,7 @@ public class TreeParser extends BaseRecognizer {
/** The worker for inContext. It's static and full of parameters for
* testing purposes.
*/
public static boolean inContext(TreeAdaptor adaptor,
public static boolean inContext(ASTAdaptor adaptor,
String[] tokenNames,
Object t,
String context)
@ -214,7 +214,7 @@ public class TreeParser extends BaseRecognizer {
}
/** Helper for static inContext */
protected static Object getAncestor(TreeAdaptor adaptor, String[] tokenNames, Object t, String goal) {
protected static Object getAncestor(ASTAdaptor adaptor, String[] tokenNames, Object t, String goal) {
while ( t!=null ) {
String name = tokenNames[adaptor.getType(t)];
if ( name.equals(goal) ) return t;

View File

@ -33,12 +33,12 @@ package org.antlr.v4.runtime.tree;
* as we discover and finish nodes.
*/
public class TreeVisitor {
protected TreeAdaptor adaptor;
protected ASTAdaptor adaptor;
public TreeVisitor(TreeAdaptor adaptor) {
public TreeVisitor(ASTAdaptor adaptor) {
this.adaptor = adaptor;
}
public TreeVisitor() { this(new CommonTreeAdaptor()); }
public TreeVisitor() { this(new CommonASTAdaptor()); }
/** Visit every node in tree t and trigger an action for each node
* before/after having visited all of its children.

View File

@ -0,0 +1,51 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree;
/** A set of utility routines useful for all kinds of ANTLR trees */
public class Trees {
/** Print out a whole tree in LISP form. toString is used on the
* node payloads to get the text for the nodes.
*/
public static String toStringTree(Tree t) {
if ( t.getChildCount()==0 ) return t.getPayload().toString();
StringBuilder buf = new StringBuilder();
buf.append("(");
buf.append(t.getPayload().toString());
buf.append(' ');
for (int i = 0; i<t.getChildCount(); i++) {
if ( i>0 ) buf.append(' ');
buf.append(t.getChild(i).toStringTree());
}
buf.append(")");
return buf.toString();
}
}

View File

@ -33,16 +33,16 @@ import org.antlr.v4.runtime.tree.*;
/** */
public class ASTViewer {
TreeAdaptor adaptor;
ASTAdaptor adaptor;
Object root;
public ASTViewer(TreeAdaptor adaptor, Object root) {
public ASTViewer(ASTAdaptor adaptor, Object root) {
this.adaptor = adaptor;
this.root = root;
}
public ASTViewer(Object root) {
this.adaptor = new CommonTreeAdaptor();
this.adaptor = new CommonASTAdaptor();
this.root = root;
}

View File

@ -35,16 +35,16 @@ import javax.swing.event.TreeModelListener;
import javax.swing.tree.*;
public class JTreeASTModel implements TreeModel {
TreeAdaptor adaptor;
ASTAdaptor adaptor;
Object root;
public JTreeASTModel(TreeAdaptor adaptor, Object root) {
public JTreeASTModel(ASTAdaptor adaptor, Object root) {
this.adaptor = adaptor;
this.root = root;
}
public JTreeASTModel(Object root) {
this.adaptor = new CommonTreeAdaptor();
this.adaptor = new CommonASTAdaptor();
this.root = root;
}

View File

@ -48,7 +48,7 @@ public class ParserFile extends OutputModelObject {
this.fileName = fileName;
Grammar g = factory.getGrammar();
TokenLabelType = g.getOption("TokenLabelType");
ASTLabelType = g.getOption("ASTLabelType", "CommonTree");
ASTLabelType = g.getOption("ASTLabelType", "CommonAST");
namedActions = new HashMap<String, Action>();
for (String name : g.namedActions.keySet()) {
GrammarAST ast = g.namedActions.get(name);

View File

@ -949,7 +949,7 @@ public abstract class BaseTest {
" <if(!treeParserStartRuleName)>\n" +
" if ( r.tree!=null ) {\n" +
" System.out.println(((Tree)r.tree).toStringTree());\n" +
" ((CommonTree)r.tree).sanityCheckParentAndChildIndexes();\n" +
" ((CommonAST)r.tree).sanityCheckParentAndChildIndexes();\n" +
" }\n" +
" <else>\n" +
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
@ -1002,13 +1002,13 @@ public abstract class BaseTest {
" TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
" <createParser>\n"+
" ParserRuleContext r = parser.<parserStartRuleName>();\n" +
" ((CommonTree)r.tree).sanityCheckParentAndChildIndexes();\n" +
" ((CommonAST)r.tree).sanityCheckParentAndChildIndexes();\n" +
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
" nodes.setTokenStream(tokens);\n" +
" <treeParserName> walker = new <treeParserName>(nodes);\n" +
" ParserRuleContext r2 = walker.<treeParserStartRuleName>();\n" +
" CommonTree rt = ((CommonTree)r2.tree);\n" +
" if ( rt!=null ) System.out.println(((CommonTree)r2.tree).toStringTree());\n" +
" CommonAST rt = ((CommonAST)r2.tree);\n" +
" if ( rt!=null ) System.out.println(((CommonAST)r2.tree).toStringTree());\n" +
" }\n" +
"}"
);

View File

@ -607,7 +607,7 @@ public class TestASTOps extends BaseTest {
"grammar T;\n" +
"options {output=AST;}\n" +
"a : ( x+=b^ )+ {" +
"System.out.print(\"x=\"+((CommonTree)$x.get(1).tree).toStringTree()+';');} ;\n" +
"System.out.print(\"x=\"+((CommonAST)$x.get(1).tree).toStringTree()+';');} ;\n" +
"b : ID;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
@ -622,7 +622,7 @@ public class TestASTOps extends BaseTest {
"grammar T;\n" +
"options {output=AST;}\n" +
"a : x+=b! x+=b {" +
"System.out.print(\"1st x=\"+((CommonTree)$x.get(0).tree).toStringTree()+';');} ;\n" +
"System.out.print(\"1st x=\"+((CommonAST)$x.get(0).tree).toStringTree()+';');} ;\n" +
"b : ID;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +

View File

@ -952,7 +952,7 @@ public class TestRewriteAST extends BaseTest {
"grammar T;\n" +
"options {output=AST;}\n" +
"tokens {BLOCK;}\n" +
"a : x+=b x+=b -> {new CommonTree()};\n"+
"a : x+=b x+=b -> {new CommonAST()};\n"+
"b : ID ;\n"+
"ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
@ -1006,7 +1006,7 @@ public class TestRewriteAST extends BaseTest {
"options { output = AST; }\n" +
"tokens { FLOAT; }\n" +
"a\n" +
" : INT -> {new CommonTree(new CommonToken(FLOAT,$INT.text+\".0\"))} \n" +
" : INT -> {new CommonTree(new CommonAST(FLOAT,$INT.text+\".0\"))} \n" +
" ; \n" +
"INT : '0'..'9'+; \n" +
"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;}; \n";