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