• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, 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 System.Collections.Generic;
36     using Antlr.Runtime.Misc;
37 
38     using StringBuilder = System.Text.StringBuilder;
39 
40     [System.Serializable]
41     public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream, IPositionTrackingStream
42     {
43         public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
44         public const int INITIAL_CALL_STACK_SIZE = 10;
45 
46         /** <summary>Pull nodes from which tree?</summary> */
47         private readonly object _root;
48 
49         /** <summary>If this tree (root) was created from a token stream, track it.</summary> */
50         protected ITokenStream tokens;
51 
52         /** <summary>What tree adaptor was used to build these trees</summary> */
53         [System.NonSerialized]
54         private ITreeAdaptor _adaptor;
55 
56         /** The tree iterator we are using */
57         private readonly TreeIterator _it;
58 
59         /** <summary>Stack of indexes used for push/pop calls</summary> */
60         private Stack<int> _calls;
61 
62         /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */
63         private bool _hasNilRoot = false;
64 
65         /** <summary>Tracks tree depth.  Level=0 means we're at root node level.</summary> */
66         private int _level = 0;
67 
68         /**
69          * Tracks the last node before the start of {@link #data} which contains
70          * position information to provide information for error reporting. This is
71          * tracked in addition to {@link #prevElement} which may or may not contain
72          * position information.
73          *
74          * @see #hasPositionInformation
75          * @see RecognitionException#extractInformationFromTreeNodeStream
76          */
77         private object _previousLocationElement;
78 
CommonTreeNodeStream( object tree )79         public CommonTreeNodeStream( object tree )
80             : this( new CommonTreeAdaptor(), tree )
81         {
82         }
83 
CommonTreeNodeStream( ITreeAdaptor adaptor, object tree )84         public CommonTreeNodeStream( ITreeAdaptor adaptor, object tree )
85         {
86             this._root = tree;
87             this._adaptor = adaptor;
88             _it = new TreeIterator( adaptor, _root );
89         }
90 
91         #region Properties
92 
93         public virtual string SourceName
94         {
95             get
96             {
97                 if ( TokenStream == null )
98                     return null;
99 
100                 return TokenStream.SourceName;
101             }
102         }
103 
104         public virtual ITokenStream TokenStream
105         {
106             get
107             {
108                 return tokens;
109             }
110 
111             set
112             {
113                 tokens = value;
114             }
115         }
116 
117         public virtual ITreeAdaptor TreeAdaptor
118         {
119             get
120             {
121                 return _adaptor;
122             }
123 
124             set
125             {
126                 _adaptor = value;
127             }
128         }
129 
130         public virtual object TreeSource
131         {
132             get
133             {
134                 return _root;
135             }
136         }
137 
138         public virtual bool UniqueNavigationNodes
139         {
140             get
141             {
142                 return false;
143             }
144 
145             set
146             {
147             }
148         }
149 
150         #endregion
151 
Reset()152         public override void Reset()
153         {
154             base.Reset();
155             _it.Reset();
156             _hasNilRoot = false;
157             _level = 0;
158             _previousLocationElement = null;
159             if ( _calls != null )
160                 _calls.Clear();
161         }
162 
NextElement()163         public override object NextElement()
164         {
165             _it.MoveNext();
166             object t = _it.Current;
167             //System.out.println("pulled "+adaptor.getType(t));
168             if ( t == _it.up )
169             {
170                 _level--;
171                 if ( _level == 0 && _hasNilRoot )
172                 {
173                     _it.MoveNext();
174                     return _it.Current; // don't give last UP; get EOF
175                 }
176             }
177             else if ( t == _it.down )
178             {
179                 _level++;
180             }
181 
182             if ( _level == 0 && TreeAdaptor.IsNil( t ) )
183             {
184                 // if nil root, scarf nil, DOWN
185                 _hasNilRoot = true;
186                 _it.MoveNext();
187                 t = _it.Current; // t is now DOWN, so get first real node next
188                 _level++;
189                 _it.MoveNext();
190                 t = _it.Current;
191             }
192 
193             return t;
194         }
195 
Dequeue()196         public override object Dequeue()
197         {
198             object result = base.Dequeue();
199             if (_p == 0 && HasPositionInformation(PreviousElement))
200                 _previousLocationElement = PreviousElement;
201 
202             return result;
203         }
204 
IsEndOfFile(object o)205         public override bool IsEndOfFile(object o)
206         {
207             return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile;
208         }
209 
LA( int i )210         public virtual int LA( int i )
211         {
212             return TreeAdaptor.GetType( LT( i ) );
213         }
214 
215         /** Make stream jump to a new location, saving old location.
216          *  Switch back with pop().
217          */
Push( int index )218         public virtual void Push( int index )
219         {
220             if ( _calls == null )
221                 _calls = new Stack<int>();
222 
223             _calls.Push( _p ); // save current index
224             Seek( index );
225         }
226 
227         /** Seek back to previous index saved during last push() call.
228          *  Return top of stack (return index).
229          */
Pop()230         public virtual int Pop()
231         {
232             int ret = _calls.Pop();
233             Seek( ret );
234             return ret;
235         }
236 
237         /**
238          * Returns an element containing position information. If {@code allowApproximateLocation} is {@code false}, then
239          * this method will return the {@code LT(1)} element if it contains position information, and otherwise return {@code null}.
240          * If {@code allowApproximateLocation} is {@code true}, then this method will return the last known element containing position information.
241          *
242          * @see #hasPositionInformation
243          */
GetKnownPositionElement(bool allowApproximateLocation)244         public object GetKnownPositionElement(bool allowApproximateLocation)
245         {
246             object node = _data[_p];
247             if (HasPositionInformation(node))
248                 return node;
249 
250             if (!allowApproximateLocation)
251                 return null;
252 
253             for (int index = _p - 1; index >= 0; index--)
254             {
255                 node = _data[index];
256                 if (HasPositionInformation(node))
257                     return node;
258             }
259 
260             return _previousLocationElement;
261         }
262 
HasPositionInformation(object node)263         public bool HasPositionInformation(object node)
264         {
265             IToken token = TreeAdaptor.GetToken(node);
266             if (token == null)
267                 return false;
268 
269             if (token.Line <= 0)
270                 return false;
271 
272             return true;
273         }
274 
275         #region Tree rewrite interface
276 
ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )277         public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
278         {
279             if ( parent != null )
280             {
281                 TreeAdaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
282             }
283         }
284 
285         #endregion
286 
ToString( object start, object stop )287         public virtual string ToString( object start, object stop )
288         {
289             // we'll have to walk from start to stop in tree; we're not keeping
290             // a complete node stream buffer
291             return "n/a";
292         }
293 
294         /** <summary>For debugging; destructive: moves tree iterator to end.</summary> */
ToTokenTypeString()295         public virtual string ToTokenTypeString()
296         {
297             Reset();
298             StringBuilder buf = new StringBuilder();
299             object o = LT( 1 );
300             int type = TreeAdaptor.GetType( o );
301             while ( type != TokenTypes.EndOfFile )
302             {
303                 buf.Append( " " );
304                 buf.Append( type );
305                 Consume();
306                 o = LT( 1 );
307                 type = TreeAdaptor.GetType( o );
308             }
309             return buf.ToString();
310         }
311     }
312 }
313