• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // #define TRACK_POSITION
34 
35 namespace Antlr.Runtime
36 {
37     using System.Collections.Generic;
38 
39     /** <summary>
40      *  A pretty quick CharStream that pulls all data from an array
41      *  directly.  Every method call counts in the lexer.  Java's
42      *  strings aren't very good so I'm avoiding.
43      *  </summary>
44      */
45     [System.Serializable]
46     public class SlimStringStream : ICharStream
47     {
48         /** <summary>The data being scanned</summary> */
49         protected string data;
50         //protected char[] data;
51 
52         /** <summary>How many characters are actually in the buffer</summary> */
53         protected int n;
54 
55         /** <summary>0..n-1 index into string of next char</summary> */
56         protected int p = 0;
57 
58 #if TRACK_POSITION
59         /** <summary>line number 1..n within the input</summary> */
60         protected int line = 1;
61 
62         /** <summary>The index of the character relative to the beginning of the line 0..n-1</summary> */
63         protected int charPositionInLine = 0;
64 #endif
65 
66         /** <summary>tracks how deep mark() calls are nested</summary> */
67         protected int markDepth = 0;
68 
69         /** <summary>
70          *  A list of CharStreamState objects that tracks the stream state
71          *  values line, charPositionInLine, and p that can change as you
72          *  move through the input stream.  Indexed from 1..markDepth.
73          *  A null is kept @ index 0.  Create upon first call to mark().
74          *  </summary>
75          */
76         protected IList<CharStreamState> markers;
77 
78         /** <summary>Track the last mark() call result value for use in rewind().</summary> */
79         protected int lastMarker;
80 
81         /** <summary>What is name or source of this char stream?</summary> */
82         public string name;
83 
SlimStringStream()84         public SlimStringStream()
85         {
86         }
87 
88         /** <summary>Copy data in string to a local char array</summary> */
SlimStringStream( string input )89         public SlimStringStream( string input )
90             : this( input, null )
91         {
92         }
93 
SlimStringStream( string input, string sourceName )94         public SlimStringStream( string input, string sourceName )
95             : this( input.ToCharArray(), input.Length, sourceName )
96         {
97         }
98 
99         /** <summary>This is the preferred constructor as no data is copied</summary> */
SlimStringStream( char[] data, int numberOfActualCharsInArray )100         public SlimStringStream( char[] data, int numberOfActualCharsInArray )
101             : this( data, numberOfActualCharsInArray, null )
102         {
103         }
104 
SlimStringStream( char[] data, int numberOfActualCharsInArray, string sourceName )105         public SlimStringStream( char[] data, int numberOfActualCharsInArray, string sourceName )
106             : this()
107         {
108             //this.data = data;
109             this.data = new string( data );
110             this.n = numberOfActualCharsInArray;
111             this.name = sourceName;
112         }
113 
114         /** <summary>
115          *  Return the current input symbol index 0..n where n indicates the
116          *  last symbol has been read.  The index is the index of char to
117          *  be returned from LA(1).
118          *  </summary>
119          */
120         public int Index
121         {
122             get
123             {
124                 return p;
125             }
126         }
127 #if TRACK_POSITION
128         public int Line
129         {
130             get
131             {
132                 return line;
133             }
134             set
135             {
136                 line = value;
137             }
138         }
139         public int CharPositionInLine
140         {
141             get
142             {
143                 return charPositionInLine;
144             }
145             set
146             {
147                 charPositionInLine = value;
148             }
149         }
150 #else
151         public int Line
152         {
153             get
154             {
155                 return -1;
156             }
157             set
158             {
159             }
160         }
161         public int CharPositionInLine
162         {
163             get
164             {
165                 return -1;
166             }
167             set
168             {
169             }
170         }
171 #endif
172 
173         /** <summary>
174          *  Reset the stream so that it's in the same state it was
175          *  when the object was created *except* the data array is not
176          *  touched.
177          *  </summary>
178          */
Reset()179         public void Reset()
180         {
181             p = 0;
182 #if TRACK_POSITION
183             line = 1;
184             charPositionInLine = 0;
185 #endif
186             markDepth = 0;
187         }
188 
Consume()189         public void Consume()
190         {
191             //System.out.println("prev p="+p+", c="+(char)data[p]);
192             if ( p < n )
193             {
194 #if TRACK_POSITION
195                 charPositionInLine++;
196                 if ( data[p] == '\n' )
197                 {
198                     /*
199                     System.out.println("newline char found on line: "+line+
200                                        "@ pos="+charPositionInLine);
201                     */
202                     line++;
203                     charPositionInLine = 0;
204                 }
205 #endif
206                 p++;
207                 //System.out.println("p moves to "+p+" (c='"+(char)data[p]+"')");
208             }
209         }
210 
LA( int i )211         public int LA( int i )
212         {
213             if ( i == 0 )
214             {
215                 return 0; // undefined
216             }
217             if ( i < 0 )
218             {
219                 i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1]
220                 if ( ( p + i - 1 ) < 0 )
221                 {
222                     return CharStreamConstants.EndOfFile; // invalid; no char before first char
223                 }
224             }
225 
226             if ( ( p + i - 1 ) >= n )
227             {
228                 //System.out.println("char LA("+i+")=EOF; p="+p);
229                 return CharStreamConstants.EndOfFile;
230             }
231             //System.out.println("char LA("+i+")="+(char)data[p+i-1]+"; p="+p);
232             //System.out.println("LA("+i+"); p="+p+" n="+n+" data.length="+data.length);
233             return data[p + i - 1];
234         }
235 
LT( int i )236         public int LT( int i )
237         {
238             return LA( i );
239         }
240 
241         public int Count
242         {
243             get
244             {
245                 return n;
246             }
247         }
248 
Mark()249         public int Mark()
250         {
251             if ( markers == null )
252             {
253                 markers = new List<CharStreamState>();
254                 markers.Add( null ); // depth 0 means no backtracking, leave blank
255             }
256             markDepth++;
257             CharStreamState state = null;
258             if ( markDepth >= markers.Count )
259             {
260                 state = new CharStreamState();
261                 markers.Add( state );
262             }
263             else
264             {
265                 state = markers[markDepth];
266             }
267             state.p = p;
268 #if TRACK_POSITION
269             state.line = line;
270             state.charPositionInLine = charPositionInLine;
271 #endif
272             lastMarker = markDepth;
273             return markDepth;
274         }
275 
Rewind( int m )276         public void Rewind( int m )
277         {
278             CharStreamState state = markers[m];
279             // restore stream state
280             Seek( state.p );
281 #if TRACK_POSITION
282             line = state.line;
283             charPositionInLine = state.charPositionInLine;
284 #endif
285             Release( m );
286         }
287 
Rewind()288         public void Rewind()
289         {
290             Rewind( lastMarker );
291         }
292 
Release( int marker )293         public void Release( int marker )
294         {
295             // unwind any other markers made after m and release m
296             markDepth = marker;
297             // release this marker
298             markDepth--;
299         }
300 
301         /** <summary>
302          *  consume() ahead until p==index; can't just set p=index as we must
303          *  update line and charPositionInLine.
304          *  </summary>
305          */
Seek( int index )306         public void Seek( int index )
307         {
308             if ( index <= p )
309             {
310                 p = index; // just jump; don't update stream state (line, ...)
311                 return;
312             }
313             // seek forward, consume until p hits index
314             while ( p < index )
315             {
316                 Consume();
317             }
318         }
319 
Substring( int start, int length )320         public string Substring( int start, int length )
321         {
322             return data.Substring( start, length );
323             //return new string( data, start, stop - start + 1 );
324         }
325 
326         public string SourceName
327         {
328             get
329             {
330                 return name;
331             }
332         }
333     }
334 }
335