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