1 /* 2 * [The "BSD licence"] 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; 36 using System.Collections.Generic; 37 38 using StringBuilder = System.Text.StringBuilder; 39 40 /** <summary> 41 * A generic tree implementation with no payload. You must subclass to 42 * actually have any user data. ANTLR v3 uses a list of children approach 43 * instead of the child-sibling approach in v2. A flat tree (a list) is 44 * an empty node whose children represent the list. An empty, but 45 * non-null node is called "nil". 46 * </summary> 47 */ 48 [System.Serializable] 49 [System.Diagnostics.DebuggerTypeProxy(typeof(AntlrRuntime_BaseTreeDebugView))] 50 public abstract class BaseTree : ITree 51 { 52 private IList<ITree> _children; 53 BaseTree()54 public BaseTree() 55 { 56 } 57 58 /** <summary> 59 * Create a new node from an existing node does nothing for BaseTree 60 * as there are no fields other than the children list, which cannot 61 * be copied as the children are not considered part of this node. 62 * </summary> 63 */ BaseTree( ITree node )64 public BaseTree( ITree node ) 65 { 66 } 67 68 /** <summary> 69 * Get the children internal List; note that if you directly mess with 70 * the list, do so at your own risk. 71 * </summary> 72 */ 73 public virtual IList<ITree> Children 74 { 75 get 76 { 77 return _children; 78 } 79 80 private set 81 { 82 _children = value; 83 } 84 } 85 86 #region ITree Members 87 88 public virtual int ChildCount 89 { 90 get 91 { 92 if ( Children == null ) 93 return 0; 94 95 return Children.Count; 96 } 97 } 98 99 /** <summary>BaseTree doesn't track parent pointers.</summary> */ 100 public virtual ITree Parent 101 { 102 get 103 { 104 return null; 105 } 106 set 107 { 108 } 109 } 110 111 /** <summary>BaseTree doesn't track child indexes.</summary> */ 112 public virtual int ChildIndex 113 { 114 get 115 { 116 return 0; 117 } 118 set 119 { 120 } 121 } 122 123 public virtual bool IsNil 124 { 125 get 126 { 127 return false; 128 } 129 } 130 131 public abstract int TokenStartIndex 132 { 133 get; 134 set; 135 } 136 137 public abstract int TokenStopIndex 138 { 139 get; 140 set; 141 } 142 143 public abstract int Type 144 { 145 get; 146 set; 147 } 148 149 public abstract string Text 150 { 151 get; 152 set; 153 } 154 155 public virtual int Line 156 { 157 get; 158 set; 159 } 160 161 public virtual int CharPositionInLine 162 { 163 get; 164 set; 165 } 166 167 #endregion 168 GetChild( int i )169 public virtual ITree GetChild( int i ) 170 { 171 if (i < 0) 172 throw new ArgumentOutOfRangeException(); 173 174 if ( Children == null || i >= Children.Count ) 175 return null; 176 177 return Children[i]; 178 } 179 GetFirstChildWithType( int type )180 public virtual ITree GetFirstChildWithType( int type ) 181 { 182 foreach ( ITree child in Children ) 183 { 184 if ( child.Type == type ) 185 return child; 186 } 187 188 return null; 189 } 190 191 /** <summary>Add t as child of this node.</summary> 192 * 193 * <remarks> 194 * Warning: if t has no children, but child does 195 * and child isNil then this routine moves children to t via 196 * t.children = child.children; i.e., without copying the array. 197 * </remarks> 198 */ AddChild( ITree t )199 public virtual void AddChild( ITree t ) 200 { 201 //System.out.println("add child "+t.toStringTree()+" "+this.toStringTree()); 202 //System.out.println("existing children: "+children); 203 if ( t == null ) 204 { 205 return; // do nothing upon addChild(null) 206 } 207 if ( t.IsNil ) 208 { 209 // t is an empty node possibly with children 210 BaseTree childTree = t as BaseTree; 211 if ( childTree != null && this.Children != null && this.Children == childTree.Children ) 212 { 213 throw new Exception( "attempt to add child list to itself" ); 214 } 215 // just add all of childTree's children to this 216 if ( t.ChildCount > 0 ) 217 { 218 if ( this.Children != null || childTree == null ) 219 { 220 if ( this.Children == null ) 221 this.Children = CreateChildrenList(); 222 223 // must copy, this has children already 224 int n = t.ChildCount; 225 for ( int i = 0; i < n; i++ ) 226 { 227 ITree c = t.GetChild( i ); 228 this.Children.Add( c ); 229 // handle double-link stuff for each child of nil root 230 c.Parent = this; 231 c.ChildIndex = Children.Count - 1; 232 } 233 } 234 else 235 { 236 // no children for this but t is a BaseTree with children; 237 // just set pointer call general freshener routine 238 this.Children = childTree.Children; 239 this.FreshenParentAndChildIndexes(); 240 } 241 } 242 } 243 else 244 { 245 // child is not nil (don't care about children) 246 if ( Children == null ) 247 { 248 Children = CreateChildrenList(); // create children list on demand 249 } 250 Children.Add( t ); 251 t.Parent = this; 252 t.ChildIndex = Children.Count - 1; 253 } 254 // System.out.println("now children are: "+children); 255 } 256 257 /** <summary>Add all elements of kids list as children of this node</summary> */ AddChildren( IEnumerable<ITree> kids )258 public virtual void AddChildren( IEnumerable<ITree> kids ) 259 { 260 if (kids == null) 261 throw new ArgumentNullException("kids"); 262 263 foreach ( ITree t in kids ) 264 AddChild( t ); 265 } 266 SetChild( int i, ITree t )267 public virtual void SetChild( int i, ITree t ) 268 { 269 if (i < 0) 270 throw new ArgumentOutOfRangeException("i"); 271 272 if ( t == null ) 273 { 274 return; 275 } 276 if ( t.IsNil ) 277 { 278 throw new ArgumentException( "Can't set single child to a list" ); 279 } 280 if ( Children == null ) 281 { 282 Children = CreateChildrenList(); 283 } 284 Children[i] = t; 285 t.Parent = this; 286 t.ChildIndex = i; 287 } 288 DeleteChild( int i )289 public virtual object DeleteChild( int i ) 290 { 291 if (i < 0) 292 throw new ArgumentOutOfRangeException("i"); 293 if (i >= ChildCount) 294 throw new ArgumentException(); 295 296 if ( Children == null ) 297 return null; 298 299 ITree killed = Children[i]; 300 Children.RemoveAt( i ); 301 // walk rest and decrement their child indexes 302 this.FreshenParentAndChildIndexes( i ); 303 return killed; 304 } 305 306 /** <summary> 307 * Delete children from start to stop and replace with t even if t is 308 * a list (nil-root tree). num of children can increase or decrease. 309 * For huge child lists, inserting children can force walking rest of 310 * children to set their childindex; could be slow. 311 * </summary> 312 */ ReplaceChildren( int startChildIndex, int stopChildIndex, object t )313 public virtual void ReplaceChildren( int startChildIndex, int stopChildIndex, object t ) 314 { 315 if (startChildIndex < 0) 316 throw new ArgumentOutOfRangeException(); 317 if (stopChildIndex < 0) 318 throw new ArgumentOutOfRangeException(); 319 if (t == null) 320 throw new ArgumentNullException("t"); 321 if (stopChildIndex < startChildIndex) 322 throw new ArgumentException(); 323 324 /* 325 System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+ 326 " with "+((BaseTree)t).toStringTree()); 327 System.out.println("in="+toStringTree()); 328 */ 329 if ( Children == null ) 330 { 331 throw new ArgumentException( "indexes invalid; no children in list" ); 332 } 333 int replacingHowMany = stopChildIndex - startChildIndex + 1; 334 int replacingWithHowMany; 335 ITree newTree = (ITree)t; 336 IList<ITree> newChildren = null; 337 // normalize to a list of children to add: newChildren 338 if ( newTree.IsNil ) 339 { 340 BaseTree baseTree = newTree as BaseTree; 341 if ( baseTree != null && baseTree.Children != null ) 342 { 343 newChildren = baseTree.Children; 344 } 345 else 346 { 347 newChildren = CreateChildrenList(); 348 int n = newTree.ChildCount; 349 for ( int i = 0; i < n; i++ ) 350 newChildren.Add( newTree.GetChild( i ) ); 351 } 352 } 353 else 354 { 355 newChildren = new List<ITree>( 1 ); 356 newChildren.Add( newTree ); 357 } 358 replacingWithHowMany = newChildren.Count; 359 int numNewChildren = newChildren.Count; 360 int delta = replacingHowMany - replacingWithHowMany; 361 // if same number of nodes, do direct replace 362 if ( delta == 0 ) 363 { 364 int j = 0; // index into new children 365 for ( int i = startChildIndex; i <= stopChildIndex; i++ ) 366 { 367 ITree child = newChildren[j]; 368 Children[i] = child; 369 child.Parent = this; 370 child.ChildIndex = i; 371 j++; 372 } 373 } 374 else if ( delta > 0 ) 375 { 376 // fewer new nodes than there were 377 // set children and then delete extra 378 for ( int j = 0; j < numNewChildren; j++ ) 379 { 380 Children[startChildIndex + j] = newChildren[j]; 381 } 382 int indexToDelete = startChildIndex + numNewChildren; 383 for ( int c = indexToDelete; c <= stopChildIndex; c++ ) 384 { 385 // delete same index, shifting everybody down each time 386 Children.RemoveAt( indexToDelete ); 387 } 388 FreshenParentAndChildIndexes( startChildIndex ); 389 } 390 else 391 { 392 // more new nodes than were there before 393 // fill in as many children as we can (replacingHowMany) w/o moving data 394 for ( int j = 0; j < replacingHowMany; j++ ) 395 { 396 Children[startChildIndex + j] = newChildren[j]; 397 } 398 int numToInsert = replacingWithHowMany - replacingHowMany; 399 for ( int j = replacingHowMany; j < replacingWithHowMany; j++ ) 400 { 401 Children.Insert( startChildIndex + j, newChildren[j] ); 402 } 403 FreshenParentAndChildIndexes( startChildIndex ); 404 } 405 //System.out.println("out="+toStringTree()); 406 } 407 408 /** <summary>Override in a subclass to change the impl of children list</summary> */ CreateChildrenList()409 protected virtual IList<ITree> CreateChildrenList() 410 { 411 return new List<ITree>(); 412 } 413 414 /** <summary>Set the parent and child index values for all child of t</summary> */ FreshenParentAndChildIndexes()415 public virtual void FreshenParentAndChildIndexes() 416 { 417 FreshenParentAndChildIndexes( 0 ); 418 } 419 FreshenParentAndChildIndexes( int offset )420 public virtual void FreshenParentAndChildIndexes( int offset ) 421 { 422 int n = ChildCount; 423 for ( int c = offset; c < n; c++ ) 424 { 425 ITree child = GetChild( c ); 426 child.ChildIndex = c; 427 child.Parent = this; 428 } 429 } 430 SanityCheckParentAndChildIndexes()431 public virtual void SanityCheckParentAndChildIndexes() 432 { 433 SanityCheckParentAndChildIndexes( null, -1 ); 434 } 435 SanityCheckParentAndChildIndexes( ITree parent, int i )436 public virtual void SanityCheckParentAndChildIndexes( ITree parent, int i ) 437 { 438 if ( parent != this.Parent ) 439 { 440 throw new InvalidOperationException( "parents don't match; expected " + parent + " found " + this.Parent ); 441 } 442 if ( i != this.ChildIndex ) 443 { 444 throw new InvalidOperationException( "child indexes don't match; expected " + i + " found " + this.ChildIndex ); 445 } 446 int n = this.ChildCount; 447 for ( int c = 0; c < n; c++ ) 448 { 449 BaseTree child = (BaseTree)this.GetChild( c ); 450 child.SanityCheckParentAndChildIndexes( this, c ); 451 } 452 } 453 454 /** <summary>Walk upwards looking for ancestor with this token type.</summary> */ HasAncestor( int ttype )455 public virtual bool HasAncestor( int ttype ) 456 { 457 return GetAncestor( ttype ) != null; 458 } 459 460 /** <summary>Walk upwards and get first ancestor with this token type.</summary> */ GetAncestor( int ttype )461 public virtual ITree GetAncestor( int ttype ) 462 { 463 ITree t = this; 464 t = t.Parent; 465 while ( t != null ) 466 { 467 if ( t.Type == ttype ) 468 return t; 469 t = t.Parent; 470 } 471 return null; 472 } 473 474 /** <summary> 475 * Return a list of all ancestors of this node. The first node of 476 * list is the root and the last is the parent of this node. 477 * </summary> 478 */ GetAncestors()479 public virtual IList<ITree> GetAncestors() 480 { 481 if ( Parent == null ) 482 return null; 483 484 List<ITree> ancestors = new List<ITree>(); 485 ITree t = this; 486 t = t.Parent; 487 while ( t != null ) 488 { 489 ancestors.Insert( 0, t ); // insert at start 490 t = t.Parent; 491 } 492 return ancestors; 493 } 494 495 /** <summary>Print out a whole tree not just a node</summary> */ ToStringTree()496 public virtual string ToStringTree() 497 { 498 if ( Children == null || Children.Count == 0 ) 499 { 500 return this.ToString(); 501 } 502 StringBuilder buf = new StringBuilder(); 503 if ( !IsNil ) 504 { 505 buf.Append( "(" ); 506 buf.Append( this.ToString() ); 507 buf.Append( ' ' ); 508 } 509 for ( int i = 0; Children != null && i < Children.Count; i++ ) 510 { 511 ITree t = Children[i]; 512 if ( i > 0 ) 513 { 514 buf.Append( ' ' ); 515 } 516 buf.Append( t.ToStringTree() ); 517 } 518 if ( !IsNil ) 519 { 520 buf.Append( ")" ); 521 } 522 return buf.ToString(); 523 } 524 525 /** <summary>Override to say how a node (not a tree) should look as text</summary> */ ToString()526 public override abstract string ToString(); 527 528 #region Tree Members DupNode()529 public abstract ITree DupNode(); 530 #endregion 531 } 532 } 533