more cleanup

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9042]
This commit is contained in:
parrt 2011-09-04 15:55:45 -08:00
parent 5c35165873
commit 01020ee1bb
10 changed files with 208 additions and 205 deletions

View File

@ -31,27 +31,8 @@ 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. */
/** An abstract syntax tree built by ANTLR during a parse 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.
*/

View File

@ -47,7 +47,10 @@ public interface ASTAdaptor {
//public List getChildren(Object root);
/** Used to track elements to left of -> for use in rewrite */
/** Used to track elements to left of -> for use in rewrite. These
* are some kind of trees, but we generically use Object
* for tree types in ANTLR.
*/
public List<Object> createElementList();
// END new v4 stuff

View File

@ -66,24 +66,14 @@ public abstract class BaseAST implements AST {
/** Get the children internal List; note that if you directly mess with
* the list, do so at your own risk.
*/
public List getChildren() {
return children;
}
public List<BaseAST> getChildren() { return children; }
public AST getFirstChildWithType(int type) {
for (int i = 0; children!=null && i < children.size(); i++) {
AST t = (AST) children.get(i);
if ( t.getType()==type ) {
return t;
}
}
return null;
return Trees.getFirstChildWithType(this, type);
}
public int getChildCount() {
if ( children==null ) {
return 0;
}
if ( children==null ) return 0;
return children.size();
}
@ -136,7 +126,7 @@ public abstract class BaseAST implements AST {
}
/** Add all elements of kids list as children of this node */
public void addChildren(List<BaseAST> kids) {
public void addChildren(List<? extends BaseAST> kids) {
if ( kids==null ) return;
for (int i = 0; i < kids.size(); i++) {
BaseAST t = kids.get(i);
@ -148,7 +138,7 @@ public abstract class BaseAST implements AST {
if ( t==null ) {
return;
}
if ( ((AST)t).isNil() ) {
if ( t.isNil() ) {
throw new IllegalArgumentException("Can't set single child to a list");
}
if ( children==null ) {
@ -185,7 +175,7 @@ public abstract class BaseAST implements AST {
return killed;
}
public boolean deleteChild(AST t) {
public boolean deleteChild(BaseAST t) {
for (int i=0; i<children.size(); i++) {
Object c = children.get(i);
if ( c == t ) {
@ -211,75 +201,9 @@ public abstract class BaseAST implements AST {
this.freshenParentAndChildIndexes(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) {
/*
System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+
" with "+((BaseTree)t).toStringTree());
System.out.println("in="+toStringTree());
*/
if ( children==null ) {
throw new IllegalArgumentException("indexes invalid; no children in list");
}
int replacingHowMany = stopChildIndex - startChildIndex + 1;
int replacingWithHowMany;
BaseAST newTree = (BaseAST)t;
List<BaseAST> newChildren = null;
// normalize to a list of children to add: newChildren
if ( newTree.isNil() ) {
newChildren = newTree.children;
}
else {
newChildren = new ArrayList(1);
newChildren.add(newTree);
}
replacingWithHowMany = newChildren.size();
int numNewChildren = newChildren.size();
int delta = replacingHowMany - replacingWithHowMany;
// if same number of nodes, do direct replace
if ( delta == 0 ) {
int j = 0; // index into new children
for (int i=startChildIndex; i<=stopChildIndex; i++) {
BaseAST child = (BaseAST)newChildren.get(j);
children.set(i, child);
child.setParent(this);
child.setChildIndex(i);
j++;
}
}
else if ( delta > 0 ) { // fewer new nodes than there were
// set children and then delete extra
for (int j=0; j<numNewChildren; j++) {
children.set(startChildIndex+j, newChildren.get(j));
}
int indexToDelete = startChildIndex+numNewChildren;
for (int c=indexToDelete; c<=stopChildIndex; c++) {
// delete same index, shifting everybody down each time
children.remove(indexToDelete);
}
freshenParentAndChildIndexes(startChildIndex);
}
else { // more new nodes than were there before
// fill in as many children as we can (replacingHowMany) w/o moving data
for (int j=0; j<replacingHowMany; j++) {
children.set(startChildIndex+j, newChildren.get(j));
}
int numToInsert = replacingWithHowMany-replacingHowMany;
for (int j=replacingHowMany; j<replacingWithHowMany; j++) {
children.add(startChildIndex+j, newChildren.get(j));
}
freshenParentAndChildIndexes(startChildIndex);
}
//System.out.println("out="+toStringTree());
}
/** Override in a subclass to change the impl of children list */
protected List createChildrenList() {
return new ArrayList();
protected List<BaseAST> createChildrenList() {
return new ArrayList<BaseAST>();
}
public boolean isNil() {
@ -314,52 +238,16 @@ public abstract class BaseAST implements AST {
}
}
public void sanityCheckParentAndChildIndexes() {
sanityCheckParentAndChildIndexes(null, -1);
}
public void sanityCheckParentAndChildIndexes(AST parent, int i) {
if ( parent!=this.getParent() ) {
throw new IllegalStateException("parents don't match; expected "+parent+" found "+this.getParent());
}
if ( i!=this.getChildIndex() ) {
throw new IllegalStateException("child index of "+this.toStringTree()+" doesn't match in "+parent.toStringTree()+"; expected "+i+" found "+this.getChildIndex());
}
int n = this.getChildCount();
for (int c = 0; c < n; c++) {
CommonAST child = (CommonAST)this.getChild(c);
child.sanityCheckParentAndChildIndexes(this, c);
}
}
/** 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 AST getAncestor(int ttype) {
AST t = this;
t = t.getParent();
while ( t!=null ) {
if ( t.getType()==ttype ) return t;
t = t.getParent();
}
return null;
}
public Tree getAncestor(int ttype) { return Trees.getAncestor(this, 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() {
if ( getParent()==null ) return null;
List<AST> ancestors = new ArrayList();
AST t = this;
t = t.getParent();
while ( t!=null ) {
ancestors.add(0, t); // insert at start
t = t.getParent();
}
return ancestors;
}
public List<? extends Tree> getAncestors() { return Trees.getAncestors(this); }
/** Don't use standard tree printing mechanism since ASTs can have nil
* root nodes.

View File

@ -33,8 +33,6 @@ 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. */
public class CommonAST extends BaseAST {
/** A single token is the payload */
@ -130,63 +128,12 @@ public class CommonAST extends BaseAST {
stopIndex = index;
}
/** For every node in this subtree, make sure it's start/stop token's
* are set. Walk depth first, visit bottom up. Only updates nodes
* with at least one token index < 0.
*/
public void setUnknownTokenBoundaries() {
if ( children==null ) {
if ( startIndex<0 || stopIndex<0 ) {
startIndex = stopIndex = token.getTokenIndex();
}
return;
}
for (int i=0; i<children.size(); i++) {
((CommonAST)children.get(i)).setUnknownTokenBoundaries();
}
if ( startIndex>=0 && stopIndex>=0 ) return; // already set
if ( children.size() > 0 ) {
CommonAST firstChild = (CommonAST)children.get(0);
CommonAST lastChild = (CommonAST)children.get(children.size()-1);
startIndex = firstChild.getTokenStartIndex();
stopIndex = lastChild.getTokenStopIndex();
}
}
// TODO: move to basetree when i settle on how runtime works
public void inspect() {
ASTViewer viewer = new ASTViewer(this);
viewer.open();
}
// TODO: move to basetree when i settle on how runtime works
// TODO: don't include this node!!
// TODO: reuse other method
public CommonAST getFirstDescendantWithType(int type) {
if ( getType()==type ) return this;
if ( children==null ) return null;
for (Object c : children) {
CommonAST t = (CommonAST)c;
if ( t.getType()==type ) return t;
CommonAST d = t.getFirstDescendantWithType(type);
if ( d!=null ) return d;
}
return null;
}
// TODO: don't include this node!!
public CommonAST getFirstDescendantWithType(Set<Integer> types) {
if ( types.contains(getType()) ) return this;
if ( children==null ) return null;
for (Object c : children) {
CommonAST t = (CommonAST)c;
if ( types.contains(t.getType()) ) return t;
CommonAST d = t.getFirstDescendantWithType(types);
if ( d!=null ) return d;
}
return null;
}
public String toString() {
if ( isNil() ) {
return "nil";

View File

@ -165,7 +165,7 @@ public class CommonASTAdaptor extends BaseASTAdaptor {
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
if ( parent!=null ) {
((CommonAST)parent).replaceChildren(startChildIndex, stopChildIndex, t);
Trees.replaceChildren((CommonAST)parent, startChildIndex, stopChildIndex, t);
}
}
}

View File

@ -34,7 +34,7 @@ import org.antlr.v4.runtime.misc.LookaheadStream;
import java.util.Stack;
public class CommonTreeNodeStream extends LookaheadStream<Object> implements TreeNodeStream {
public class CommonASTNodeStream extends LookaheadStream<Object> implements TreeNodeStream {
public static final int DEFAULT_INITIAL_BUFFER_SIZE = 100;
public static final int INITIAL_CALL_STACK_SIZE = 10;
@ -59,11 +59,11 @@ public class CommonTreeNodeStream extends LookaheadStream<Object> implements Tre
/** Tracks tree depth. Level=0 means we're at root node level. */
protected int level = 0;
public CommonTreeNodeStream(Object tree) {
public CommonASTNodeStream(Object tree) {
this(new CommonASTAdaptor(), tree);
}
public CommonTreeNodeStream(ASTAdaptor adaptor, Object tree) {
public CommonASTNodeStream(ASTAdaptor adaptor, Object tree) {
this.root = tree;
this.adaptor = adaptor;
it = new TreeIterator(adaptor,root);

View File

@ -93,8 +93,8 @@ public class TreeFilter extends TreeParser {
if ( t==null ) return;
try {
// share TreeParser object but not parsing-related state
input = new CommonTreeNodeStream(originalAdaptor, t);
((CommonTreeNodeStream)input).setTokenStream(originalTokenStream);
input = new CommonASTNodeStream(originalAdaptor, t);
((CommonASTNodeStream)input).setTokenStream(originalTokenStream);
whichRule.rule();
}
catch (RecognitionException e) { ; }

View File

@ -29,6 +29,8 @@
package org.antlr.v4.runtime.tree;
import java.util.*;
/** 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
@ -48,4 +50,186 @@ public class Trees {
return buf.toString();
}
/** Walk upwards and get first ancestor with this token type. */
public static AST getAncestor(AST t, int ttype) {
t = t.getParent();
while ( t!=null ) {
if ( t.getType()==ttype ) return t;
t = t.getParent();
}
return null;
}
/** 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 static List<? extends Tree> getAncestors(Tree t) {
if ( t.getParent()==null ) return null;
List<Tree> ancestors = new ArrayList<Tree>();
t = t.getParent();
while ( t!=null ) {
ancestors.add(0, t); // insert at start
t = t.getParent();
}
return ancestors;
}
public static AST getFirstChildWithType(AST t, int type) {
for (int i = 0; i<t.getChildCount(); i++) {
AST c = (AST)t.getChild(i);
if ( c.getType()==type ) {
return c;
}
}
return null;
}
/** 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 static void replaceChildren(BaseAST tree, int startChildIndex, int stopChildIndex, Object t) {
/*
System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+
" with "+((BaseTree)t).toStringTree());
System.out.println("in="+toStringTree());
*/
if ( tree.getChildCount()==0 ) {
throw new IllegalArgumentException("indexes invalid; no children in list");
}
int replacingHowMany = stopChildIndex - startChildIndex + 1;
int replacingWithHowMany;
BaseAST newTree = (BaseAST)t;
List<BaseAST> newChildren = null;
// normalize to a list of children to add: newChildren
if ( newTree.isNil() ) {
newChildren = newTree.children;
}
else {
newChildren = new ArrayList<BaseAST>(1);
newChildren.add(newTree);
}
replacingWithHowMany = newChildren.size();
int numNewChildren = newChildren.size();
int delta = replacingHowMany - replacingWithHowMany;
// if same number of nodes, do direct replace
if ( delta == 0 ) {
int j = 0; // index into new children
for (int i=startChildIndex; i<=stopChildIndex; i++) {
BaseAST child = (BaseAST)newChildren.get(j);
tree.setChild(i, child);
child.setParent(tree);
child.setChildIndex(i);
j++;
}
}
else if ( delta > 0 ) { // fewer new nodes than there were
// set children and then delete extra
for (int j=0; j<numNewChildren; j++) {
tree.setChild(startChildIndex + j, newChildren.get(j));
}
int indexToDelete = startChildIndex+numNewChildren;
for (int c=indexToDelete; c<=stopChildIndex; c++) {
// delete same index, shifting everybody down each time
tree.children.remove(indexToDelete);
}
tree.freshenParentAndChildIndexes(startChildIndex);
}
else { // more new nodes than were there before
// fill in as many children as we can (replacingHowMany) w/o moving data
for (int j=0; j<replacingHowMany; j++) {
tree.children.set(startChildIndex+j, newChildren.get(j));
}
int numToInsert = replacingWithHowMany-replacingHowMany;
for (int j=replacingHowMany; j<replacingWithHowMany; j++) {
tree.children.add(startChildIndex+j, newChildren.get(j));
}
tree.freshenParentAndChildIndexes(startChildIndex);
}
//System.out.println("out="+toStringTree());
}
public static AST dupTree(ASTAdaptor adaptor, AST t, AST parent) {
if ( t==null ) {
return null;
}
AST newTree = (AST)adaptor.dupNode(t);
// ensure new subtree root has parent/child index set
adaptor.setChildIndex(newTree, adaptor.getChildIndex(t)); // same index in new tree
adaptor.setParent(newTree, parent);
int n = adaptor.getChildCount(t);
for (int i = 0; i < n; i++) {
AST child = (AST)adaptor.getChild(t, i);
Object newSubTree = dupTree(adaptor, child, t);
adaptor.addChild(newTree, newSubTree);
}
return newTree;
}
/** For every node in this subtree, make sure it's start/stop token's
* are set. Walk depth first, visit bottom up. Only updates nodes
* with at least one token index < 0.
*/
public static void setUnknownTokenBoundaries(CommonAST t) {
if ( t.children==null ) {
if ( t.startIndex<0 || t.stopIndex<0 ) {
t.startIndex = t.stopIndex = t.token.getTokenIndex();
}
return;
}
int n = t.getChildCount();
for (int i = 0; i < n; i++) {
setUnknownTokenBoundaries((CommonAST) t.getChild(i));
}
if ( t.startIndex>=0 && t.stopIndex>=0 ) return; // already set
if ( t.getChildCount() > 0 ) {
CommonAST firstChild = (CommonAST)t.getChild(0);
CommonAST lastChild = (CommonAST)t.getChild(t.getChildCount()-1);
t.startIndex = firstChild.getTokenStartIndex();
t.stopIndex = lastChild.getTokenStopIndex();
}
}
public static AST getFirstDescendantWithType(AST t, final int type) {
return getFirstDescendantWithType(t, new TreeSet<Integer>() {{add(type);}} );
}
// TODO: don't include this node!!
public static AST getFirstDescendantWithType(AST t, Set<Integer> types) {
if ( types.contains(t.getType()) ) return t;
if ( t.getChildCount()==0 ) return null;
int n = t.getChildCount();
for (int i = 0; i < n; i++) {
AST c = (AST)t.getChild(i);
if ( types.contains(c.getType()) ) return c;
AST d = getFirstDescendantWithType(c, types);
if ( d!=null ) return d;
}
return null;
}
public static void sanityCheckParentAndChildIndexes(BaseAST t) {
sanityCheckParentAndChildIndexes(t, null, -1);
}
public static void sanityCheckParentAndChildIndexes(BaseAST t, AST parent, int i) {
if ( parent!=t.getParent() ) {
throw new IllegalStateException("parents don't match; expected "+
parent+" found "+t.getParent());
}
if ( i!=t.getChildIndex() ) {
throw new IllegalStateException("child index of "+t.toStringTree()+
" doesn't match in "+
parent.toStringTree()+
"; expected "+i+" found "+
t.getChildIndex());
}
int n = t.getChildCount();
for (int c = 0; c < n; c++) {
BaseAST child = t.getChild(c);
sanityCheckParentAndChildIndexes(child, t, c);
}
}
}

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" +
" ((CommonAST)r.tree).sanityCheckParentAndChildIndexes();\n" +
" Trees.sanityCheckParentAndChildIndexes((CommonAST)r.tree);\n" +
" }\n" +
" <else>\n" +
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
@ -1002,7 +1002,7 @@ public abstract class BaseTest {
" TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
" <createParser>\n"+
" ParserRuleContext r = parser.<parserStartRuleName>();\n" +
" ((CommonAST)r.tree).sanityCheckParentAndChildIndexes();\n" +
" Trees.sanityCheckParentAndChildIndexes((CommonAST)r.tree);\n" +
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
" nodes.setTokenStream(tokens);\n" +
" <treeParserName> walker = new <treeParserName>(nodes);\n" +

View File

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