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