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 ArgumentNullException = System.ArgumentNullException; 35 using CLSCompliant = System.CLSCompliantAttribute; 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 /** <summary>A single token is the payload</summary> */ 48 [CLSCompliant(false)] 49 public 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 CommonTree(CommonTree node)68 public CommonTree(CommonTree node) 69 : base(node) { 70 if (node == null) 71 throw new ArgumentNullException("node"); 72 73 this.token = node.token; 74 this.startIndex = node.startIndex; 75 this.stopIndex = node.stopIndex; 76 } 77 CommonTree(IToken t)78 public CommonTree(IToken t) { 79 this.token = t; 80 } 81 82 #region Properties 83 public override int CharPositionInLine { 84 get { 85 if (token == null || token.CharPositionInLine == -1) { 86 if (ChildCount > 0) { 87 return Children[0].CharPositionInLine; 88 } 89 return 0; 90 } 91 return token.CharPositionInLine; 92 } 93 set { 94 base.CharPositionInLine = value; 95 } 96 } 97 public override int ChildIndex { 98 get { 99 return childIndex; 100 } 101 set { 102 childIndex = value; 103 } 104 } 105 public override bool IsNil { 106 get { 107 return token == null; 108 } 109 } 110 public override int Line { 111 get { 112 if (token == null || token.Line == 0) { 113 if (ChildCount > 0) { 114 return Children[0].Line; 115 } 116 return 0; 117 } 118 return token.Line; 119 } 120 set { 121 base.Line = value; 122 } 123 } 124 public override ITree Parent { 125 get { 126 return parent; 127 } 128 set { 129 parent = (CommonTree)value; 130 } 131 } 132 public override string Text { 133 get { 134 if (token == null) 135 return null; 136 137 return token.Text; 138 } 139 set { 140 } 141 } 142 public virtual IToken Token { 143 get { 144 return token; 145 } 146 set { 147 token = value; 148 } 149 } 150 public override int TokenStartIndex { 151 get { 152 if (startIndex == -1 && token != null) { 153 return token.TokenIndex; 154 } 155 return startIndex; 156 } 157 set { 158 startIndex = value; 159 } 160 } 161 public override int TokenStopIndex { 162 get { 163 if (stopIndex == -1 && token != null) { 164 return token.TokenIndex; 165 } 166 return stopIndex; 167 } 168 set { 169 stopIndex = value; 170 } 171 } 172 public override int Type { 173 get { 174 if (token == null) 175 return TokenTypes.Invalid; 176 177 return token.Type; 178 } 179 set { 180 } 181 } 182 #endregion 183 DupNode()184 public override ITree DupNode() { 185 return new CommonTree(this); 186 } 187 188 /** <summary> 189 * For every node in this subtree, make sure it's start/stop token's 190 * are set. Walk depth first, visit bottom up. Only updates nodes 191 * with at least one token index < 0. 192 * </summary> 193 */ SetUnknownTokenBoundaries()194 public virtual void SetUnknownTokenBoundaries() { 195 if (Children == null) { 196 if (startIndex < 0 || stopIndex < 0) { 197 startIndex = stopIndex = token.TokenIndex; 198 } 199 return; 200 } 201 for (int i = 0; i < Children.Count; i++) { 202 ((CommonTree)Children[i]).SetUnknownTokenBoundaries(); 203 } 204 if (startIndex >= 0 && stopIndex >= 0) 205 return; // already set 206 if (Children.Count > 0) { 207 CommonTree firstChild = (CommonTree)Children[0]; 208 CommonTree lastChild = (CommonTree)Children[Children.Count - 1]; 209 startIndex = firstChild.TokenStartIndex; 210 stopIndex = lastChild.TokenStopIndex; 211 } 212 } 213 ToString()214 public override string ToString() { 215 if (IsNil) { 216 return "nil"; 217 } 218 if (Type == TokenTypes.Invalid) { 219 return "<errornode>"; 220 } 221 if (token == null) { 222 return string.Empty; 223 } 224 return token.Text; 225 } 226 } 227 } 228