00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime.tree;
00029
00030 import org.antlr.runtime.Token;
00031 import org.antlr.runtime.TokenStream;
00032
00033 import java.util.ArrayList;
00034 import java.util.List;
00035 import java.util.Stack;
00036
00049 public class UnBufferedTreeNodeStream implements TreeNodeStream {
00050 public static final int INITIAL_LOOKAHEAD_BUFFER_SIZE = 5;
00051
00053 protected boolean uniqueNavigationNodes = false;
00054
00056 protected Object root;
00057
00059 protected TokenStream tokens;
00060
00062 TreeAdaptor adaptor;
00063
00068 protected Stack nodeStack = new Stack();
00069
00073 protected Stack indexStack = new Stack();
00074
00076 protected Object currentNode;
00077
00079 protected Object previousNode;
00080
00084 protected int currentChildIndex;
00085
00089 protected int absoluteNodeIndex;
00090
00095 protected Object[] lookahead = new Object[INITIAL_LOOKAHEAD_BUFFER_SIZE];
00096
00098 protected int head;
00099
00103 protected int tail;
00104
00110 protected class TreeWalkState {
00111 int currentChildIndex;
00112 int absoluteNodeIndex;
00113 Object currentNode;
00114 Object previousNode;
00116 int nodeStackSize;
00118 int indexStackSize;
00119 Object[] lookahead;
00120 }
00121
00127 protected List markers;
00128
00130 protected int markDepth = 0;
00131
00133 protected int lastMarker;
00134
00135
00136
00137 protected Object down;
00138 protected Object up;
00139 protected Object eof;
00140
00141 public UnBufferedTreeNodeStream(Object tree) {
00142 this(new CommonTreeAdaptor(), tree);
00143 }
00144
00145 public UnBufferedTreeNodeStream(TreeAdaptor adaptor, Object tree) {
00146 this.root = tree;
00147 this.adaptor = adaptor;
00148 reset();
00149 down = adaptor.create(Token.DOWN, "DOWN");
00150 up = adaptor.create(Token.UP, "UP");
00151 eof = adaptor.create(Token.EOF, "EOF");
00152 }
00153
00154 public void reset() {
00155 currentNode = root;
00156 previousNode = null;
00157 currentChildIndex = -1;
00158 absoluteNodeIndex = -1;
00159 head = tail = 0;
00160 }
00161
00162
00163
00164 public Object get(int i) {
00165 throw new UnsupportedOperationException("stream is unbuffered");
00166 }
00167
00178 public Object LT(int k) {
00179
00180 if ( k==-1 ) {
00181 return previousNode;
00182 }
00183 if ( k<0 ) {
00184 throw new IllegalArgumentException("tree node streams cannot look backwards more than 1 node");
00185 }
00186 if ( k==0 ) {
00187 return Tree.INVALID_NODE;
00188 }
00189 fill(k);
00190 return lookahead[(head+k-1)%lookahead.length];
00191 }
00192
00196 public Object getTreeSource() {
00197 return root;
00198 }
00199
00200 public String getSourceName() {
00201 return getTokenStream().getSourceName();
00202 }
00203
00204 public TokenStream getTokenStream() {
00205 return tokens;
00206 }
00207
00208 public void setTokenStream(TokenStream tokens) {
00209 this.tokens = tokens;
00210 }
00211
00213 protected void fill(int k) {
00214 int n = getLookaheadSize();
00215
00216 for (int i=1; i<=k-n; i++) {
00217 next();
00218 }
00219 }
00220
00226 protected void addLookahead(Object node) {
00227
00228 lookahead[tail] = node;
00229 tail = (tail+1)%lookahead.length;
00230 if ( tail==head ) {
00231
00232
00233 Object[] bigger = new Object[2*lookahead.length];
00234
00235 int remainderHeadToEnd = lookahead.length-head;
00236 System.arraycopy(lookahead, head, bigger, 0, remainderHeadToEnd);
00237
00238 System.arraycopy(lookahead, 0, bigger, remainderHeadToEnd, tail);
00239 lookahead = bigger;
00240 head = 0;
00241 tail += remainderHeadToEnd;
00242 }
00243 }
00244
00245
00246
00247 public void consume() {
00248
00249
00250
00251
00252
00253
00254 fill(1);
00255 absoluteNodeIndex++;
00256 previousNode = lookahead[head];
00257 head = (head+1) % lookahead.length;
00258 }
00259
00260 public int LA(int i) {
00261 Object t = LT(i);
00262 if ( t==null ) {
00263 return Token.INVALID_TOKEN_TYPE;
00264 }
00265 return adaptor.getType(t);
00266 }
00267
00272 public int mark() {
00273 if ( markers==null ) {
00274 markers = new ArrayList();
00275 markers.add(null);
00276 }
00277 markDepth++;
00278 TreeWalkState state = null;
00279 if ( markDepth>=markers.size() ) {
00280 state = new TreeWalkState();
00281 markers.add(state);
00282 }
00283 else {
00284 state = (TreeWalkState)markers.get(markDepth);
00285 }
00286 state.absoluteNodeIndex = absoluteNodeIndex;
00287 state.currentChildIndex = currentChildIndex;
00288 state.currentNode = currentNode;
00289 state.previousNode = previousNode;
00290 state.nodeStackSize = nodeStack.size();
00291 state.indexStackSize = indexStack.size();
00292
00293 int n = getLookaheadSize();
00294 int i=0;
00295 state.lookahead = new Object[n];
00296 for (int k=1; k<=n; k++,i++) {
00297 state.lookahead[i] = LT(k);
00298 }
00299 lastMarker = markDepth;
00300 return markDepth;
00301 }
00302
00303 public void release(int marker) {
00304
00305 markDepth = marker;
00306
00307 markDepth--;
00308 }
00309
00316 public void rewind(int marker) {
00317 if ( markers==null ) {
00318 return;
00319 }
00320 TreeWalkState state = (TreeWalkState)markers.get(marker);
00321 absoluteNodeIndex = state.absoluteNodeIndex;
00322 currentChildIndex = state.currentChildIndex;
00323 currentNode = state.currentNode;
00324 previousNode = state.previousNode;
00325
00326 nodeStack.setSize(state.nodeStackSize);
00327 indexStack.setSize(state.indexStackSize);
00328 head = tail = 0;
00329 for (; tail<state.lookahead.length; tail++) {
00330 lookahead[tail] = state.lookahead[tail];
00331 }
00332 release(marker);
00333 }
00334
00335 public void rewind() {
00336 rewind(lastMarker);
00337 }
00338
00342 public void seek(int index) {
00343 if ( index<this.index() ) {
00344 throw new IllegalArgumentException("can't seek backwards in node stream");
00345 }
00346
00347 while ( this.index()<index ) {
00348 consume();
00349 }
00350 }
00351
00352 public int index() {
00353 return absoluteNodeIndex+1;
00354 }
00355
00361 public int size() {
00362 CommonTreeNodeStream s = new CommonTreeNodeStream(root);
00363 return s.size();
00364 }
00365
00380 public Object next() {
00381
00382 if ( currentNode==null ) {
00383 addLookahead(eof);
00384
00385
00386 return null;
00387 }
00388
00389
00390 if ( currentChildIndex==-1 ) {
00391 return handleRootNode();
00392 }
00393
00394
00395 if ( currentChildIndex<adaptor.getChildCount(currentNode) ) {
00396 return visitChild(currentChildIndex);
00397 }
00398
00399
00400 walkBackToMostRecentNodeWithUnvisitedChildren();
00401 if ( currentNode!=null ) {
00402 return visitChild(currentChildIndex);
00403 }
00404
00405 return null;
00406 }
00407
00408 protected Object handleRootNode() {
00409 Object node;
00410 node = currentNode;
00411
00412 currentChildIndex = 0;
00413 if ( adaptor.isNil(node) ) {
00414
00415 node = visitChild(currentChildIndex);
00416 }
00417 else {
00418 addLookahead(node);
00419 if ( adaptor.getChildCount(currentNode)==0 ) {
00420
00421 currentNode = null;
00422 }
00423 }
00424 return node;
00425 }
00426
00427 protected Object visitChild(int child) {
00428 Object node = null;
00429
00430 nodeStack.push(currentNode);
00431 indexStack.push(new Integer(child));
00432 if ( child==0 && !adaptor.isNil(currentNode) ) {
00433 addNavigationNode(Token.DOWN);
00434 }
00435
00436 currentNode = adaptor.getChild(currentNode,child);
00437 currentChildIndex = 0;
00438 node = currentNode;
00439 addLookahead(node);
00440 walkBackToMostRecentNodeWithUnvisitedChildren();
00441 return node;
00442 }
00443
00448 protected void addNavigationNode(final int ttype) {
00449 Object navNode = null;
00450 if ( ttype==Token.DOWN ) {
00451 if ( hasUniqueNavigationNodes() ) {
00452 navNode = adaptor.create(Token.DOWN, "DOWN");
00453 }
00454 else {
00455 navNode = down;
00456 }
00457 }
00458 else {
00459 if ( hasUniqueNavigationNodes() ) {
00460 navNode = adaptor.create(Token.UP, "UP");
00461 }
00462 else {
00463 navNode = up;
00464 }
00465 }
00466 addLookahead(navNode);
00467 }
00468
00470 protected void walkBackToMostRecentNodeWithUnvisitedChildren() {
00471 while ( currentNode!=null &&
00472 currentChildIndex>=adaptor.getChildCount(currentNode) )
00473 {
00474 currentNode = nodeStack.pop();
00475 if ( currentNode==null ) {
00476 return;
00477 }
00478 currentChildIndex = ((Integer)indexStack.pop()).intValue();
00479 currentChildIndex++;
00480 if ( currentChildIndex>=adaptor.getChildCount(currentNode) ) {
00481 if ( !adaptor.isNil(currentNode) ) {
00482 addNavigationNode(Token.UP);
00483 }
00484 if ( currentNode==root ) {
00485 currentNode = null;
00486 }
00487 }
00488 }
00489 }
00490
00491 public TreeAdaptor getTreeAdaptor() {
00492 return adaptor;
00493 }
00494
00495 public boolean hasUniqueNavigationNodes() {
00496 return uniqueNavigationNodes;
00497 }
00498
00499 public void setUniqueNavigationNodes(boolean uniqueNavigationNodes) {
00500 this.uniqueNavigationNodes = uniqueNavigationNodes;
00501 }
00502
00503 public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
00504 throw new UnsupportedOperationException("can't do stream rewrites yet");
00505 }
00506
00511 public String toString() {
00512 return toString(root, null);
00513 }
00514
00515 protected int getLookaheadSize() {
00516 return tail<head?(lookahead.length-head+tail):(tail-head);
00517 }
00518
00519 public String toString(Object start, Object stop) {
00520 if ( start==null ) {
00521 return null;
00522 }
00523
00524 if ( tokens!=null ) {
00525
00526
00527
00528 int beginTokenIndex = adaptor.getTokenStartIndex(start);
00529 int endTokenIndex = adaptor.getTokenStopIndex(stop);
00530 if ( stop!=null && adaptor.getType(stop)==Token.UP ) {
00531 endTokenIndex = adaptor.getTokenStopIndex(start);
00532 }
00533 else {
00534 endTokenIndex = size()-1;
00535 }
00536 return tokens.toString(beginTokenIndex, endTokenIndex);
00537 }
00538 StringBuffer buf = new StringBuffer();
00539 toStringWork(start, stop, buf);
00540 return buf.toString();
00541 }
00542
00543 protected void toStringWork(Object p, Object stop, StringBuffer buf) {
00544 if ( !adaptor.isNil(p) ) {
00545 String text = adaptor.getText(p);
00546 if ( text==null ) {
00547 text = " "+String.valueOf(adaptor.getType(p));
00548 }
00549 buf.append(text);
00550 }
00551 if ( p==stop ) {
00552 return;
00553 }
00554 int n = adaptor.getChildCount(p);
00555 if ( n>0 && !adaptor.isNil(p) ) {
00556 buf.append(" ");
00557 buf.append(Token.DOWN);
00558 }
00559 for (int c=0; c<n; c++) {
00560 Object child = adaptor.getChild(p,c);
00561 toStringWork(child, stop, buf);
00562 }
00563 if ( n>0 && !adaptor.isNil(p) ) {
00564 buf.append(" ");
00565 buf.append(Token.UP);
00566 }
00567 }
00568 }
00569