Home | History | Annotate | Download | only in tree
      1 /*
      2  [The "BSD license"]
      3  Copyright (c) 2005-2009 Terence Parr
      4  All rights reserved.
      5 
      6  Redistribution and use in source and binary forms, with or without
      7  modification, are permitted provided that the following conditions
      8  are met:
      9  1. Redistributions of source code must retain the above copyright
     10      notice, this list of conditions and the following disclaimer.
     11  2. Redistributions in binary form must reproduce the above copyright
     12      notice, this list of conditions and the following disclaimer in the
     13      documentation and/or other materials provided with the distribution.
     14  3. The name of the author may not be used to endorse or promote products
     15      derived from this software without specific prior written permission.
     16 
     17  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 package org.antlr.runtime.tree;
     29 
     30 import org.antlr.runtime.Token;
     31 
     32 /** A tree node that is wrapper for a Token object.  After 3.0 release
     33  *  while building tree rewrite stuff, it became clear that computing
     34  *  parent and child index is very difficult and cumbersome.  Better to
     35  *  spend the space in every tree node.  If you don't want these extra
     36  *  fields, it's easy to cut them out in your own BaseTree subclass.
     37  */
     38 public class CommonTree extends BaseTree {
     39 	/** A single token is the payload */
     40 	public Token token;
     41 
     42 	/** What token indexes bracket all tokens associated with this node
     43 	 *  and below?
     44 	 */
     45 	protected int startIndex=-1, stopIndex=-1;
     46 
     47 	/** Who is the parent node of this node; if null, implies node is root */
     48 	public CommonTree parent;
     49 
     50 	/** What index is this node in the child list? Range: 0..n-1 */
     51 	public int childIndex = -1;
     52 
     53 	public CommonTree() { }
     54 
     55 	public CommonTree(CommonTree node) {
     56 		super(node);
     57 		this.token = node.token;
     58 		this.startIndex = node.startIndex;
     59 		this.stopIndex = node.stopIndex;
     60 	}
     61 
     62 	public CommonTree(Token t) {
     63 		this.token = t;
     64 	}
     65 
     66 	public Token getToken() {
     67 		return token;
     68 	}
     69 
     70 	public Tree dupNode() {
     71 		return new CommonTree(this);
     72 	}
     73 
     74 	public boolean isNil() {
     75 		return token==null;
     76 	}
     77 
     78 	public int getType() {
     79 		if ( token==null ) {
     80 			return Token.INVALID_TOKEN_TYPE;
     81 		}
     82 		return token.getType();
     83 	}
     84 
     85 	public String getText() {
     86 		if ( token==null ) {
     87 			return null;
     88 		}
     89 		return token.getText();
     90 	}
     91 
     92 	public int getLine() {
     93 		if ( token==null || token.getLine()==0 ) {
     94 			if ( getChildCount()>0 ) {
     95 				return getChild(0).getLine();
     96 			}
     97 			return 0;
     98 		}
     99 		return token.getLine();
    100 	}
    101 
    102 	public int getCharPositionInLine() {
    103 		if ( token==null || token.getCharPositionInLine()==-1 ) {
    104 			if ( getChildCount()>0 ) {
    105 				return getChild(0).getCharPositionInLine();
    106 			}
    107 			return 0;
    108 		}
    109 		return token.getCharPositionInLine();
    110 	}
    111 
    112 	public int getTokenStartIndex() {
    113 		if ( startIndex==-1 && token!=null ) {
    114 			return token.getTokenIndex();
    115 		}
    116 		return startIndex;
    117 	}
    118 
    119 	public void setTokenStartIndex(int index) {
    120 		startIndex = index;
    121 	}
    122 
    123 	public int getTokenStopIndex() {
    124 		if ( stopIndex==-1 && token!=null ) {
    125 			return token.getTokenIndex();
    126 		}
    127 		return stopIndex;
    128 	}
    129 
    130 	public void setTokenStopIndex(int index) {
    131 		stopIndex = index;
    132 	}
    133 
    134     /** For every node in this subtree, make sure it's start/stop token's
    135      *  are set.  Walk depth first, visit bottom up.  Only updates nodes
    136      *  with at least one token index < 0.
    137      */
    138     public void setUnknownTokenBoundaries() {
    139         if ( children==null ) {
    140             if ( startIndex<0 || stopIndex<0 ) {
    141                 startIndex = stopIndex = token.getTokenIndex();
    142             }
    143             return;
    144         }
    145         for (int i=0; i<children.size(); i++) {
    146             ((CommonTree)children.get(i)).setUnknownTokenBoundaries();
    147         }
    148         if ( startIndex>=0 && stopIndex>=0 ) return; // already set
    149         if ( children.size() > 0 ) {
    150             CommonTree firstChild = (CommonTree)children.get(0);
    151             CommonTree lastChild = (CommonTree)children.get(children.size()-1);
    152             startIndex = firstChild.getTokenStartIndex();
    153             stopIndex = lastChild.getTokenStopIndex();
    154         }
    155     }
    156 
    157 	public int getChildIndex() {
    158 		return childIndex;
    159 	}
    160 
    161 	public Tree getParent() {
    162 		return parent;
    163 	}
    164 
    165 	public void setParent(Tree t) {
    166 		this.parent = (CommonTree)t;
    167 	}
    168 
    169 	public void setChildIndex(int index) {
    170 		this.childIndex = index;
    171 	}
    172 
    173 	public String toString() {
    174 		if ( isNil() ) {
    175 			return "nil";
    176 		}
    177 		if ( getType()==Token.INVALID_TOKEN_TYPE ) {
    178 			return "<errornode>";
    179 		}
    180 		if ( token==null ) {
    181 			return null;
    182 		}
    183 		return token.getText();
    184 	}
    185 }
    186