forked from jasder/antlr
more cleanup
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9042]
This commit is contained in:
parent
5c35165873
commit
01020ee1bb
|
@ -31,27 +31,8 @@ package org.antlr.v4.runtime.tree;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
import java.util.List;
|
/** An abstract syntax tree built by ANTLR during a parse or tree parse. */
|
||||||
|
|
||||||
/** An abstract syntax tree built by ANTLR during a parcel or tree parse. */
|
|
||||||
public interface AST extends SyntaxTree {
|
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
|
/** Indicates the node is a nil node but may still have children, meaning
|
||||||
* the tree is a flat list.
|
* the tree is a flat list.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -47,7 +47,10 @@ public interface ASTAdaptor {
|
||||||
|
|
||||||
//public List getChildren(Object root);
|
//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();
|
public List<Object> createElementList();
|
||||||
|
|
||||||
// END new v4 stuff
|
// END new v4 stuff
|
||||||
|
|
|
@ -66,24 +66,14 @@ public abstract class BaseAST implements AST {
|
||||||
/** Get the children internal List; note that if you directly mess with
|
/** Get the children internal List; note that if you directly mess with
|
||||||
* the list, do so at your own risk.
|
* the list, do so at your own risk.
|
||||||
*/
|
*/
|
||||||
public List getChildren() {
|
public List<BaseAST> getChildren() { return children; }
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AST getFirstChildWithType(int type) {
|
public AST getFirstChildWithType(int type) {
|
||||||
for (int i = 0; children!=null && i < children.size(); i++) {
|
return Trees.getFirstChildWithType(this, type);
|
||||||
AST t = (AST) children.get(i);
|
|
||||||
if ( t.getType()==type ) {
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChildCount() {
|
public int getChildCount() {
|
||||||
if ( children==null ) {
|
if ( children==null ) return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return children.size();
|
return children.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +126,7 @@ public abstract class BaseAST implements AST {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add all elements of kids list as children of this node */
|
/** 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;
|
if ( kids==null ) return;
|
||||||
for (int i = 0; i < kids.size(); i++) {
|
for (int i = 0; i < kids.size(); i++) {
|
||||||
BaseAST t = kids.get(i);
|
BaseAST t = kids.get(i);
|
||||||
|
@ -148,7 +138,7 @@ public abstract class BaseAST implements AST {
|
||||||
if ( t==null ) {
|
if ( t==null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( ((AST)t).isNil() ) {
|
if ( t.isNil() ) {
|
||||||
throw new IllegalArgumentException("Can't set single child to a list");
|
throw new IllegalArgumentException("Can't set single child to a list");
|
||||||
}
|
}
|
||||||
if ( children==null ) {
|
if ( children==null ) {
|
||||||
|
@ -185,7 +175,7 @@ public abstract class BaseAST implements AST {
|
||||||
return killed;
|
return killed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean deleteChild(AST t) {
|
public boolean deleteChild(BaseAST t) {
|
||||||
for (int i=0; i<children.size(); i++) {
|
for (int i=0; i<children.size(); i++) {
|
||||||
Object c = children.get(i);
|
Object c = children.get(i);
|
||||||
if ( c == t ) {
|
if ( c == t ) {
|
||||||
|
@ -211,75 +201,9 @@ public abstract class BaseAST implements AST {
|
||||||
this.freshenParentAndChildIndexes(i);
|
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 */
|
/** Override in a subclass to change the impl of children list */
|
||||||
protected List createChildrenList() {
|
protected List<BaseAST> createChildrenList() {
|
||||||
return new ArrayList();
|
return new ArrayList<BaseAST>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNil() {
|
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. */
|
/** Walk upwards looking for ancestor with this token type. */
|
||||||
public boolean hasAncestor(int ttype) { return getAncestor(ttype)!=null; }
|
public boolean hasAncestor(int ttype) { return getAncestor(ttype)!=null; }
|
||||||
|
|
||||||
/** Walk upwards and get first ancestor with this token type. */
|
/** Walk upwards and get first ancestor with this token type. */
|
||||||
public AST getAncestor(int ttype) {
|
public Tree getAncestor(int ttype) { return Trees.getAncestor(this, ttype); }
|
||||||
AST t = this;
|
|
||||||
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
|
/** 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.
|
* list is the root and the last is the parent of this node.
|
||||||
*/
|
*/
|
||||||
public List getAncestors() {
|
public List<? extends Tree> getAncestors() { return Trees.getAncestors(this); }
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Don't use standard tree printing mechanism since ASTs can have nil
|
/** Don't use standard tree printing mechanism since ASTs can have nil
|
||||||
* root nodes.
|
* root nodes.
|
||||||
|
|
|
@ -33,8 +33,6 @@ import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.misc.Interval;
|
import org.antlr.v4.runtime.misc.Interval;
|
||||||
import org.antlr.v4.runtime.tree.gui.ASTViewer;
|
import org.antlr.v4.runtime.tree.gui.ASTViewer;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/** A tree node that is wrapper for a Token object. */
|
/** A tree node that is wrapper for a Token object. */
|
||||||
public class CommonAST extends BaseAST {
|
public class CommonAST extends BaseAST {
|
||||||
/** A single token is the payload */
|
/** A single token is the payload */
|
||||||
|
@ -130,63 +128,12 @@ public class CommonAST extends BaseAST {
|
||||||
stopIndex = index;
|
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
|
// TODO: move to basetree when i settle on how runtime works
|
||||||
public void inspect() {
|
public void inspect() {
|
||||||
ASTViewer viewer = new ASTViewer(this);
|
ASTViewer viewer = new ASTViewer(this);
|
||||||
viewer.open();
|
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() {
|
public String toString() {
|
||||||
if ( isNil() ) {
|
if ( isNil() ) {
|
||||||
return "nil";
|
return "nil";
|
||||||
|
|
|
@ -165,7 +165,7 @@ public class CommonASTAdaptor extends BaseASTAdaptor {
|
||||||
|
|
||||||
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
|
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
|
||||||
if ( parent!=null ) {
|
if ( parent!=null ) {
|
||||||
((CommonAST)parent).replaceChildren(startChildIndex, stopChildIndex, t);
|
Trees.replaceChildren((CommonAST)parent, startChildIndex, stopChildIndex, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.antlr.v4.runtime.misc.LookaheadStream;
|
||||||
|
|
||||||
import java.util.Stack;
|
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 DEFAULT_INITIAL_BUFFER_SIZE = 100;
|
||||||
public static final int INITIAL_CALL_STACK_SIZE = 10;
|
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. */
|
/** Tracks tree depth. Level=0 means we're at root node level. */
|
||||||
protected int level = 0;
|
protected int level = 0;
|
||||||
|
|
||||||
public CommonTreeNodeStream(Object tree) {
|
public CommonASTNodeStream(Object tree) {
|
||||||
this(new CommonASTAdaptor(), tree);
|
this(new CommonASTAdaptor(), tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonTreeNodeStream(ASTAdaptor adaptor, Object tree) {
|
public CommonASTNodeStream(ASTAdaptor adaptor, Object tree) {
|
||||||
this.root = tree;
|
this.root = tree;
|
||||||
this.adaptor = adaptor;
|
this.adaptor = adaptor;
|
||||||
it = new TreeIterator(adaptor,root);
|
it = new TreeIterator(adaptor,root);
|
|
@ -93,8 +93,8 @@ public class TreeFilter extends TreeParser {
|
||||||
if ( t==null ) return;
|
if ( t==null ) return;
|
||||||
try {
|
try {
|
||||||
// share TreeParser object but not parsing-related state
|
// share TreeParser object but not parsing-related state
|
||||||
input = new CommonTreeNodeStream(originalAdaptor, t);
|
input = new CommonASTNodeStream(originalAdaptor, t);
|
||||||
((CommonTreeNodeStream)input).setTokenStream(originalTokenStream);
|
((CommonASTNodeStream)input).setTokenStream(originalTokenStream);
|
||||||
whichRule.rule();
|
whichRule.rule();
|
||||||
}
|
}
|
||||||
catch (RecognitionException e) { ; }
|
catch (RecognitionException e) { ; }
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
package org.antlr.v4.runtime.tree;
|
package org.antlr.v4.runtime.tree;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/** A set of utility routines useful for all kinds of ANTLR trees */
|
/** A set of utility routines useful for all kinds of ANTLR trees */
|
||||||
public class Trees {
|
public class Trees {
|
||||||
/** Print out a whole tree in LISP form. toString is used on the
|
/** Print out a whole tree in LISP form. toString is used on the
|
||||||
|
@ -48,4 +50,186 @@ public class Trees {
|
||||||
return buf.toString();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -949,7 +949,7 @@ public abstract class BaseTest {
|
||||||
" <if(!treeParserStartRuleName)>\n" +
|
" <if(!treeParserStartRuleName)>\n" +
|
||||||
" if ( r.tree!=null ) {\n" +
|
" if ( r.tree!=null ) {\n" +
|
||||||
" System.out.println(((Tree)r.tree).toStringTree());\n" +
|
" System.out.println(((Tree)r.tree).toStringTree());\n" +
|
||||||
" ((CommonAST)r.tree).sanityCheckParentAndChildIndexes();\n" +
|
" Trees.sanityCheckParentAndChildIndexes((CommonAST)r.tree);\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" <else>\n" +
|
" <else>\n" +
|
||||||
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
|
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
|
||||||
|
@ -1002,7 +1002,7 @@ public abstract class BaseTest {
|
||||||
" TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
|
" TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
|
||||||
" <createParser>\n"+
|
" <createParser>\n"+
|
||||||
" ParserRuleContext r = parser.<parserStartRuleName>();\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" +
|
" CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
|
||||||
" nodes.setTokenStream(tokens);\n" +
|
" nodes.setTokenStream(tokens);\n" +
|
||||||
" <treeParserName> walker = new <treeParserName>(nodes);\n" +
|
" <treeParserName> walker = new <treeParserName>(nodes);\n" +
|
||||||
|
|
|
@ -1006,7 +1006,7 @@ public class TestRewriteAST extends BaseTest {
|
||||||
"options { output = AST; }\n" +
|
"options { output = AST; }\n" +
|
||||||
"tokens { FLOAT; }\n" +
|
"tokens { FLOAT; }\n" +
|
||||||
"a\n" +
|
"a\n" +
|
||||||
" : INT -> {new CommonTree(new CommonAST(FLOAT,$INT.text+\".0\"))} \n" +
|
" : INT -> {new CommonAST(new CommonAST(FLOAT,$INT.text+\".0\"))} \n" +
|
||||||
" ; \n" +
|
" ; \n" +
|
||||||
"INT : '0'..'9'+; \n" +
|
"INT : '0'..'9'+; \n" +
|
||||||
"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;}; \n";
|
"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;}; \n";
|
||||||
|
|
Loading…
Reference in New Issue