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, Tunnel Vision Laboratories, LLC 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 289 /** Insert child t at child position i (0..n-1) by shifting children 290 * i+1..n-1 to the right one position. Set parent / indexes properly 291 * but does NOT collapse nil-rooted t's that come in here like addChild. 292 */ InsertChild(int i, ITree t)293 public virtual void InsertChild(int i, ITree t) 294 { 295 if (i < 0) 296 throw new ArgumentOutOfRangeException("i"); 297 if (i > ChildCount) 298 throw new ArgumentException(); 299 300 if (i == ChildCount) 301 { 302 AddChild(t); 303 return; 304 } 305 306 Children.Insert(i, t); 307 308 // walk others to increment their child indexes 309 // set index, parent of this one too 310 this.FreshenParentAndChildIndexes(i); 311 } 312 DeleteChild( int i )313 public virtual object DeleteChild( int i ) 314 { 315 if (i < 0) 316 throw new ArgumentOutOfRangeException("i"); 317 if (i >= ChildCount) 318 throw new ArgumentException(); 319 320 if ( Children == null ) 321 return null; 322 323 ITree killed = Children[i]; 324 Children.RemoveAt( i ); 325 // walk rest and decrement their child indexes 326 this.FreshenParentAndChildIndexes( i ); 327 return killed; 328 } 329 330 /** <summary> 331 * Delete children from start to stop and replace with t even if t is 332 * a list (nil-root tree). num of children can increase or decrease. 333 * For huge child lists, inserting children can force walking rest of 334 * children to set their childindex; could be slow. 335 * </summary> 336 */ ReplaceChildren( int startChildIndex, int stopChildIndex, object t )337 public virtual void ReplaceChildren( int startChildIndex, int stopChildIndex, object t ) 338 { 339 if (startChildIndex < 0) 340 throw new ArgumentOutOfRangeException(); 341 if (stopChildIndex < 0) 342 throw new ArgumentOutOfRangeException(); 343 if (t == null) 344 throw new ArgumentNullException("t"); 345 if (stopChildIndex < startChildIndex) 346 throw new ArgumentException(); 347 348 /* 349 System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+ 350 " with "+((BaseTree)t).toStringTree()); 351 System.out.println("in="+toStringTree()); 352 */ 353 if ( Children == null ) 354 { 355 throw new ArgumentException( "indexes invalid; no children in list" ); 356 } 357 int replacingHowMany = stopChildIndex - startChildIndex + 1; 358 int replacingWithHowMany; 359 ITree newTree = (ITree)t; 360 IList<ITree> newChildren = null; 361 // normalize to a list of children to add: newChildren 362 if ( newTree.IsNil ) 363 { 364 BaseTree baseTree = newTree as BaseTree; 365 if ( baseTree != null && baseTree.Children != null ) 366 { 367 newChildren = baseTree.Children; 368 } 369 else 370 { 371 newChildren = CreateChildrenList(); 372 int n = newTree.ChildCount; 373 for ( int i = 0; i < n; i++ ) 374 newChildren.Add( newTree.GetChild( i ) ); 375 } 376 } 377 else 378 { 379 newChildren = new List<ITree>( 1 ); 380 newChildren.Add( newTree ); 381 } 382 replacingWithHowMany = newChildren.Count; 383 int numNewChildren = newChildren.Count; 384 int delta = replacingHowMany - replacingWithHowMany; 385 // if same number of nodes, do direct replace 386 if ( delta == 0 ) 387 { 388 int j = 0; // index into new children 389 for ( int i = startChildIndex; i <= stopChildIndex; i++ ) 390 { 391 ITree child = newChildren[j]; 392 Children[i] = child; 393 child.Parent = this; 394 child.ChildIndex = i; 395 j++; 396 } 397 } 398 else if ( delta > 0 ) 399 { 400 // fewer new nodes than there were 401 // set children and then delete extra 402 for ( int j = 0; j < numNewChildren; j++ ) 403 { 404 Children[startChildIndex + j] = newChildren[j]; 405 } 406 int indexToDelete = startChildIndex + numNewChildren; 407 for ( int c = indexToDelete; c <= stopChildIndex; c++ ) 408 { 409 // delete same index, shifting everybody down each time 410 Children.RemoveAt( indexToDelete ); 411 } 412 FreshenParentAndChildIndexes( startChildIndex ); 413 } 414 else 415 { 416 // more new nodes than were there before 417 // fill in as many children as we can (replacingHowMany) w/o moving data 418 for ( int j = 0; j < replacingHowMany; j++ ) 419 { 420 Children[startChildIndex + j] = newChildren[j]; 421 } 422 int numToInsert = replacingWithHowMany - replacingHowMany; 423 for ( int j = replacingHowMany; j < replacingWithHowMany; j++ ) 424 { 425 Children.Insert( startChildIndex + j, newChildren[j] ); 426 } 427 FreshenParentAndChildIndexes( startChildIndex ); 428 } 429 //System.out.println("out="+toStringTree()); 430 } 431 432 /** <summary>Override in a subclass to change the impl of children list</summary> */ CreateChildrenList()433 protected virtual IList<ITree> CreateChildrenList() 434 { 435 return new List<ITree>(); 436 } 437 438 /** <summary>Set the parent and child index values for all child of t</summary> */ FreshenParentAndChildIndexes()439 public virtual void FreshenParentAndChildIndexes() 440 { 441 FreshenParentAndChildIndexes( 0 ); 442 } 443 FreshenParentAndChildIndexes( int offset )444 public virtual void FreshenParentAndChildIndexes( int offset ) 445 { 446 int n = ChildCount; 447 for ( int c = offset; c < n; c++ ) 448 { 449 ITree child = GetChild( c ); 450 child.ChildIndex = c; 451 child.Parent = this; 452 } 453 } 454 FreshenParentAndChildIndexesDeeply()455 public virtual void FreshenParentAndChildIndexesDeeply() 456 { 457 FreshenParentAndChildIndexesDeeply(0); 458 } 459 FreshenParentAndChildIndexesDeeply(int offset)460 public virtual void FreshenParentAndChildIndexesDeeply(int offset) 461 { 462 int n = ChildCount; 463 for (int c = offset; c < n; c++) 464 { 465 ITree child = GetChild(c); 466 child.ChildIndex = c; 467 child.Parent = this; 468 BaseTree baseTree = child as BaseTree; 469 if (baseTree != null) 470 baseTree.FreshenParentAndChildIndexesDeeply(); 471 } 472 } 473 SanityCheckParentAndChildIndexes()474 public virtual void SanityCheckParentAndChildIndexes() 475 { 476 SanityCheckParentAndChildIndexes( null, -1 ); 477 } 478 SanityCheckParentAndChildIndexes( ITree parent, int i )479 public virtual void SanityCheckParentAndChildIndexes( ITree parent, int i ) 480 { 481 if ( parent != this.Parent ) 482 { 483 throw new InvalidOperationException( "parents don't match; expected " + parent + " found " + this.Parent ); 484 } 485 if ( i != this.ChildIndex ) 486 { 487 throw new InvalidOperationException( "child indexes don't match; expected " + i + " found " + this.ChildIndex ); 488 } 489 int n = this.ChildCount; 490 for ( int c = 0; c < n; c++ ) 491 { 492 BaseTree child = (BaseTree)this.GetChild( c ); 493 child.SanityCheckParentAndChildIndexes( this, c ); 494 } 495 } 496 497 /** <summary>Walk upwards looking for ancestor with this token type.</summary> */ HasAncestor( int ttype )498 public virtual bool HasAncestor( int ttype ) 499 { 500 return GetAncestor( ttype ) != null; 501 } 502 503 /** <summary>Walk upwards and get first ancestor with this token type.</summary> */ GetAncestor( int ttype )504 public virtual ITree GetAncestor( int ttype ) 505 { 506 ITree t = this; 507 t = t.Parent; 508 while ( t != null ) 509 { 510 if ( t.Type == ttype ) 511 return t; 512 t = t.Parent; 513 } 514 return null; 515 } 516 517 /** <summary> 518 * Return a list of all ancestors of this node. The first node of 519 * list is the root and the last is the parent of this node. 520 * </summary> 521 */ GetAncestors()522 public virtual IList<ITree> GetAncestors() 523 { 524 if ( Parent == null ) 525 return null; 526 527 List<ITree> ancestors = new List<ITree>(); 528 ITree t = this; 529 t = t.Parent; 530 while ( t != null ) 531 { 532 ancestors.Insert( 0, t ); // insert at start 533 t = t.Parent; 534 } 535 return ancestors; 536 } 537 538 /** <summary>Print out a whole tree not just a node</summary> */ ToStringTree()539 public virtual string ToStringTree() 540 { 541 if ( Children == null || Children.Count == 0 ) 542 { 543 return this.ToString(); 544 } 545 StringBuilder buf = new StringBuilder(); 546 if ( !IsNil ) 547 { 548 buf.Append( "(" ); 549 buf.Append( this.ToString() ); 550 buf.Append( ' ' ); 551 } 552 for ( int i = 0; Children != null && i < Children.Count; i++ ) 553 { 554 ITree t = Children[i]; 555 if ( i > 0 ) 556 { 557 buf.Append( ' ' ); 558 } 559 buf.Append( t.ToStringTree() ); 560 } 561 if ( !IsNil ) 562 { 563 buf.Append( ")" ); 564 } 565 return buf.ToString(); 566 } 567 568 /** <summary>Override to say how a node (not a tree) should look as text</summary> */ ToString()569 public override abstract string ToString(); 570 571 #region Tree Members DupNode()572 public abstract ITree DupNode(); 573 #endregion 574 } 575 } 576