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 ArgumentNullException = System.ArgumentNullException; 36 37 /** <summary> 38 * A tree node that is wrapper for a Token object. After 3.0 release 39 * while building tree rewrite stuff, it became clear that computing 40 * parent and child index is very difficult and cumbersome. Better to 41 * spend the space in every tree node. If you don't want these extra 42 * fields, it's easy to cut them out in your own BaseTree subclass. 43 * </summary> 44 */ 45 [System.Serializable] 46 public class CommonTree : BaseTree 47 { 48 /** <summary>A single token is the payload</summary> */ 49 private IToken _token; 50 51 /** <summary> 52 * What token indexes bracket all tokens associated with this node 53 * and below? 54 * </summary> 55 */ 56 protected int startIndex = -1; 57 protected int stopIndex = -1; 58 59 /** <summary>Who is the parent node of this node; if null, implies node is root</summary> */ 60 CommonTree parent; 61 62 /** <summary>What index is this node in the child list? Range: 0..n-1</summary> */ 63 int childIndex = -1; 64 CommonTree()65 public CommonTree() 66 { 67 } 68 CommonTree( CommonTree node )69 public CommonTree( CommonTree node ) 70 : base( node ) 71 { 72 if (node == null) 73 throw new ArgumentNullException("node"); 74 75 this.Token = node.Token; 76 this.startIndex = node.startIndex; 77 this.stopIndex = node.stopIndex; 78 } 79 CommonTree( IToken t )80 public CommonTree( IToken t ) 81 { 82 this.Token = t; 83 } 84 85 #region Properties 86 87 public override int CharPositionInLine 88 { 89 get 90 { 91 if ( Token == null || Token.CharPositionInLine == -1 ) 92 { 93 if ( ChildCount > 0 ) 94 return Children[0].CharPositionInLine; 95 96 return 0; 97 } 98 return Token.CharPositionInLine; 99 } 100 101 set 102 { 103 base.CharPositionInLine = value; 104 } 105 } 106 107 public override int ChildIndex 108 { 109 get 110 { 111 return childIndex; 112 } 113 114 set 115 { 116 childIndex = value; 117 } 118 } 119 120 public override bool IsNil 121 { 122 get 123 { 124 return Token == null; 125 } 126 } 127 128 public override int Line 129 { 130 get 131 { 132 if ( Token == null || Token.Line == 0 ) 133 { 134 if ( ChildCount > 0 ) 135 return Children[0].Line; 136 137 return 0; 138 } 139 140 return Token.Line; 141 } 142 143 set 144 { 145 base.Line = value; 146 } 147 } 148 149 public override ITree Parent 150 { 151 get 152 { 153 return parent; 154 } 155 156 set 157 { 158 parent = (CommonTree)value; 159 } 160 } 161 162 public override string Text 163 { 164 get 165 { 166 if ( Token == null ) 167 return null; 168 169 return Token.Text; 170 } 171 172 set 173 { 174 } 175 } 176 177 public IToken Token 178 { 179 get 180 { 181 return _token; 182 } 183 184 set 185 { 186 _token = value; 187 } 188 } 189 190 public override int TokenStartIndex 191 { 192 get 193 { 194 if ( startIndex == -1 && Token != null ) 195 return Token.TokenIndex; 196 197 return startIndex; 198 } 199 200 set 201 { 202 startIndex = value; 203 } 204 } 205 206 public override int TokenStopIndex 207 { 208 get 209 { 210 if ( stopIndex == -1 && Token != null ) 211 { 212 return Token.TokenIndex; 213 } 214 return stopIndex; 215 } 216 217 set 218 { 219 stopIndex = value; 220 } 221 } 222 223 public override int Type 224 { 225 get 226 { 227 if ( Token == null ) 228 return TokenTypes.Invalid; 229 230 return Token.Type; 231 } 232 233 set 234 { 235 } 236 } 237 238 #endregion 239 DupNode()240 public override ITree DupNode() 241 { 242 return new CommonTree( this ); 243 } 244 245 /** <summary> 246 * For every node in this subtree, make sure it's start/stop token's 247 * are set. Walk depth first, visit bottom up. Only updates nodes 248 * with at least one token index < 0. 249 * </summary> 250 */ SetUnknownTokenBoundaries()251 public virtual void SetUnknownTokenBoundaries() 252 { 253 if ( Children == null ) 254 { 255 if ( startIndex < 0 || stopIndex < 0 ) 256 startIndex = stopIndex = Token.TokenIndex; 257 258 return; 259 } 260 261 foreach (ITree childTree in Children) 262 { 263 CommonTree commonTree = childTree as CommonTree; 264 if (commonTree == null) 265 continue; 266 267 commonTree.SetUnknownTokenBoundaries(); 268 } 269 270 if ( startIndex >= 0 && stopIndex >= 0 ) 271 return; // already set 272 273 if ( Children.Count > 0 ) 274 { 275 ITree firstChild = Children[0]; 276 ITree lastChild = Children[Children.Count - 1]; 277 startIndex = firstChild.TokenStartIndex; 278 stopIndex = lastChild.TokenStopIndex; 279 } 280 } 281 ToString()282 public override string ToString() 283 { 284 if (IsNil) 285 return "nil"; 286 287 if (Type == TokenTypes.Invalid) 288 return "<errornode>"; 289 290 if (Token == null) 291 return string.Empty; 292 293 return Token.Text; 294 } 295 } 296 } 297