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 33namespace Antlr.Runtime.Tree { 34 using System.Collections.Generic; 35 using Antlr.Runtime.Misc; 36 37 using StringBuilder = System.Text.StringBuilder; 38 using NotSupportedException = System.NotSupportedException; 39 40 [System.Serializable] 41 public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream { 42 public const int DEFAULT_INITIAL_BUFFER_SIZE = 100; 43 public const int INITIAL_CALL_STACK_SIZE = 10; 44 45 /** <summary>Pull nodes from which tree?</summary> */ 46 object _root; 47 48 /** <summary>If this tree (root) was created from a token stream, track it.</summary> */ 49 protected ITokenStream tokens; 50 51 /** <summary>What tree adaptor was used to build these trees</summary> */ 52 [System.NonSerialized] 53 ITreeAdaptor _adaptor; 54 55 /** The tree iterator we are using */ 56 TreeIterator _it; 57 58 /** <summary>Stack of indexes used for push/pop calls</summary> */ 59 Stack<int> _calls; 60 61 /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */ 62 bool _hasNilRoot = false; 63 64 /** <summary>Tracks tree depth. Level=0 means we're at root node level.</summary> */ 65 int _level = 0; 66 67 public CommonTreeNodeStream(object tree) 68 : this(new CommonTreeAdaptor(), tree) { 69 } 70 71 public CommonTreeNodeStream(ITreeAdaptor adaptor, object tree) { 72 this._root = tree; 73 this._adaptor = adaptor; 74 _it = new TreeIterator(adaptor, _root); 75 } 76 77 #region Properties 78 79 public virtual string SourceName { 80 get { 81 if (TokenStream == null) 82 return null; 83 84 return TokenStream.SourceName; 85 } 86 } 87 88 public virtual ITokenStream TokenStream { 89 get { 90 return tokens; 91 } 92 set { 93 tokens = value; 94 } 95 } 96 97 public virtual ITreeAdaptor TreeAdaptor { 98 get { 99 return _adaptor; 100 } 101 102 set { 103 _adaptor = value; 104 } 105 } 106 107 public virtual object TreeSource { 108 get { 109 return _root; 110 } 111 } 112 113 public virtual bool UniqueNavigationNodes { 114 get { 115 return false; 116 } 117 118 set { 119 } 120 } 121 122 #endregion 123 124 public virtual void Reset() { 125 base.Clear(); 126 _it.Reset(); 127 _hasNilRoot = false; 128 _level = 0; 129 if (_calls != null) 130 _calls.Clear(); 131 } 132 133 public override object NextElement() { 134 _it.MoveNext(); 135 object t = _it.Current; 136 //System.out.println("pulled "+adaptor.getType(t)); 137 if (t == _it.up) { 138 _level--; 139 if (_level == 0 && _hasNilRoot) { 140 _it.MoveNext(); 141 return _it.Current; // don't give last UP; get EOF 142 } 143 } else if (t == _it.down) { 144 _level++; 145 } 146 147 if (_level == 0 && TreeAdaptor.IsNil(t)) { 148 // if nil root, scarf nil, DOWN 149 _hasNilRoot = true; 150 _it.MoveNext(); 151 t = _it.Current; // t is now DOWN, so get first real node next 152 _level++; 153 _it.MoveNext(); 154 t = _it.Current; 155 } 156 157 return t; 158 } 159 160 public override bool IsEndOfFile(object o) { 161 return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile; 162 } 163 164 public virtual int LA(int i) { 165 return TreeAdaptor.GetType(LT(i)); 166 } 167 168 /** Make stream jump to a new location, saving old location. 169 * Switch back with pop(). 170 */ 171 public virtual void Push(int index) { 172 if (_calls == null) { 173 _calls = new Stack<int>(); 174 } 175 _calls.Push(_p); // save current index 176 Seek(index); 177 } 178 179 /** Seek back to previous index saved during last push() call. 180 * Return top of stack (return index). 181 */ 182 public virtual int Pop() { 183 int ret = _calls.Pop(); 184 Seek(ret); 185 return ret; 186 } 187 188 #region Tree rewrite interface 189 190 public virtual void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) { 191 if (parent != null) { 192 TreeAdaptor.ReplaceChildren(parent, startChildIndex, stopChildIndex, t); 193 } 194 } 195 196 #endregion 197 198 public virtual string ToString(object start, object stop) { 199 // we'll have to walk from start to stop in tree; we're not keeping 200 // a complete node stream buffer 201 return "n/a"; 202 } 203 204 /** <summary>For debugging; destructive: moves tree iterator to end.</summary> */ 205 public virtual string ToTokenTypeString() { 206 Reset(); 207 StringBuilder buf = new StringBuilder(); 208 object o = LT(1); 209 int type = TreeAdaptor.GetType(o); 210 while (type != TokenTypes.EndOfFile) { 211 buf.Append(" "); 212 buf.Append(type); 213 Consume(); 214 o = LT(1); 215 type = TreeAdaptor.GetType(o); 216 } 217 return buf.ToString(); 218 } 219 } 220} 221