1 /* 2 * [The "BSD license"] 3 * Copyright (c) 2011 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 namespace Antlr.Runtime.Tree 34 { 35 using System.Collections.Generic; 36 using Antlr.Runtime.Misc; 37 38 using StringBuilder = System.Text.StringBuilder; 39 40 [System.Serializable] 41 public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream, IPositionTrackingStream 42 { 43 public const int DEFAULT_INITIAL_BUFFER_SIZE = 100; 44 public const int INITIAL_CALL_STACK_SIZE = 10; 45 46 /** <summary>Pull nodes from which tree?</summary> */ 47 private readonly object _root; 48 49 /** <summary>If this tree (root) was created from a token stream, track it.</summary> */ 50 protected ITokenStream tokens; 51 52 /** <summary>What tree adaptor was used to build these trees</summary> */ 53 [System.NonSerialized] 54 private ITreeAdaptor _adaptor; 55 56 /** The tree iterator we are using */ 57 private readonly TreeIterator _it; 58 59 /** <summary>Stack of indexes used for push/pop calls</summary> */ 60 private Stack<int> _calls; 61 62 /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */ 63 private bool _hasNilRoot = false; 64 65 /** <summary>Tracks tree depth. Level=0 means we're at root node level.</summary> */ 66 private int _level = 0; 67 68 /** 69 * Tracks the last node before the start of {@link #data} which contains 70 * position information to provide information for error reporting. This is 71 * tracked in addition to {@link #prevElement} which may or may not contain 72 * position information. 73 * 74 * @see #hasPositionInformation 75 * @see RecognitionException#extractInformationFromTreeNodeStream 76 */ 77 private object _previousLocationElement; 78 CommonTreeNodeStream( object tree )79 public CommonTreeNodeStream( object tree ) 80 : this( new CommonTreeAdaptor(), tree ) 81 { 82 } 83 CommonTreeNodeStream( ITreeAdaptor adaptor, object tree )84 public CommonTreeNodeStream( ITreeAdaptor adaptor, object tree ) 85 { 86 this._root = tree; 87 this._adaptor = adaptor; 88 _it = new TreeIterator( adaptor, _root ); 89 } 90 91 #region Properties 92 93 public virtual string SourceName 94 { 95 get 96 { 97 if ( TokenStream == null ) 98 return null; 99 100 return TokenStream.SourceName; 101 } 102 } 103 104 public virtual ITokenStream TokenStream 105 { 106 get 107 { 108 return tokens; 109 } 110 111 set 112 { 113 tokens = value; 114 } 115 } 116 117 public virtual ITreeAdaptor TreeAdaptor 118 { 119 get 120 { 121 return _adaptor; 122 } 123 124 set 125 { 126 _adaptor = value; 127 } 128 } 129 130 public virtual object TreeSource 131 { 132 get 133 { 134 return _root; 135 } 136 } 137 138 public virtual bool UniqueNavigationNodes 139 { 140 get 141 { 142 return false; 143 } 144 145 set 146 { 147 } 148 } 149 150 #endregion 151 Reset()152 public override void Reset() 153 { 154 base.Reset(); 155 _it.Reset(); 156 _hasNilRoot = false; 157 _level = 0; 158 _previousLocationElement = null; 159 if ( _calls != null ) 160 _calls.Clear(); 161 } 162 NextElement()163 public override object NextElement() 164 { 165 _it.MoveNext(); 166 object t = _it.Current; 167 //System.out.println("pulled "+adaptor.getType(t)); 168 if ( t == _it.up ) 169 { 170 _level--; 171 if ( _level == 0 && _hasNilRoot ) 172 { 173 _it.MoveNext(); 174 return _it.Current; // don't give last UP; get EOF 175 } 176 } 177 else if ( t == _it.down ) 178 { 179 _level++; 180 } 181 182 if ( _level == 0 && TreeAdaptor.IsNil( t ) ) 183 { 184 // if nil root, scarf nil, DOWN 185 _hasNilRoot = true; 186 _it.MoveNext(); 187 t = _it.Current; // t is now DOWN, so get first real node next 188 _level++; 189 _it.MoveNext(); 190 t = _it.Current; 191 } 192 193 return t; 194 } 195 Dequeue()196 public override object Dequeue() 197 { 198 object result = base.Dequeue(); 199 if (_p == 0 && HasPositionInformation(PreviousElement)) 200 _previousLocationElement = PreviousElement; 201 202 return result; 203 } 204 IsEndOfFile(object o)205 public override bool IsEndOfFile(object o) 206 { 207 return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile; 208 } 209 LA( int i )210 public virtual int LA( int i ) 211 { 212 return TreeAdaptor.GetType( LT( i ) ); 213 } 214 215 /** Make stream jump to a new location, saving old location. 216 * Switch back with pop(). 217 */ Push( int index )218 public virtual void Push( int index ) 219 { 220 if ( _calls == null ) 221 _calls = new Stack<int>(); 222 223 _calls.Push( _p ); // save current index 224 Seek( index ); 225 } 226 227 /** Seek back to previous index saved during last push() call. 228 * Return top of stack (return index). 229 */ Pop()230 public virtual int Pop() 231 { 232 int ret = _calls.Pop(); 233 Seek( ret ); 234 return ret; 235 } 236 237 /** 238 * Returns an element containing position information. If {@code allowApproximateLocation} is {@code false}, then 239 * this method will return the {@code LT(1)} element if it contains position information, and otherwise return {@code null}. 240 * If {@code allowApproximateLocation} is {@code true}, then this method will return the last known element containing position information. 241 * 242 * @see #hasPositionInformation 243 */ GetKnownPositionElement(bool allowApproximateLocation)244 public object GetKnownPositionElement(bool allowApproximateLocation) 245 { 246 object node = _data[_p]; 247 if (HasPositionInformation(node)) 248 return node; 249 250 if (!allowApproximateLocation) 251 return null; 252 253 for (int index = _p - 1; index >= 0; index--) 254 { 255 node = _data[index]; 256 if (HasPositionInformation(node)) 257 return node; 258 } 259 260 return _previousLocationElement; 261 } 262 HasPositionInformation(object node)263 public bool HasPositionInformation(object node) 264 { 265 IToken token = TreeAdaptor.GetToken(node); 266 if (token == null) 267 return false; 268 269 if (token.Line <= 0) 270 return false; 271 272 return true; 273 } 274 275 #region Tree rewrite interface 276 ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )277 public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ) 278 { 279 if ( parent != null ) 280 { 281 TreeAdaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t ); 282 } 283 } 284 285 #endregion 286 ToString( object start, object stop )287 public virtual string ToString( object start, object stop ) 288 { 289 // we'll have to walk from start to stop in tree; we're not keeping 290 // a complete node stream buffer 291 return "n/a"; 292 } 293 294 /** <summary>For debugging; destructive: moves tree iterator to end.</summary> */ ToTokenTypeString()295 public virtual string ToTokenTypeString() 296 { 297 Reset(); 298 StringBuilder buf = new StringBuilder(); 299 object o = LT( 1 ); 300 int type = TreeAdaptor.GetType( o ); 301 while ( type != TokenTypes.EndOfFile ) 302 { 303 buf.Append( " " ); 304 buf.Append( type ); 305 Consume(); 306 o = LT( 1 ); 307 type = TreeAdaptor.GetType( o ); 308 } 309 return buf.ToString(); 310 } 311 } 312 } 313