KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fri > patterns > interpreter > parsergenerator > lexer > Input


1 package fri.patterns.interpreter.parsergenerator.lexer;
2
3 import java.io.*;
4
5 /**
6     Lexer input wrapper. The input can be InputStream, Reader, File, String or StringBuffer.
7     If Input is InputStream, no Reader will be used, which means that the input reads bytes
8     and not characters.
9     <p>
10     The read() methode returns EOF (-1) when there is no more input.
11     
12     @author (c) 2002, Fritz Ritzberger
13 */

14
15 class Input
16 {
17     public static final int EOF = -1;
18     private InputStream inputStream;
19     private Reader reader;
20     private int [] buffer;
21     private int readPos, readLen;
22     private int readOffset;
23     private boolean eof = false;
24     private boolean buffering = false;
25     
26     
27     Input(Object JavaDoc input)
28         throws IOException
29     {
30         if (input instanceof InputStream)
31             this.inputStream = input instanceof BufferedInputStream ? (InputStream)input : new BufferedInputStream((InputStream)input);
32         else
33         if (input instanceof Reader)
34             this.reader = input instanceof BufferedReader ? (Reader)input : new BufferedReader((Reader)input);
35         else
36         if (input instanceof File)
37             this.reader = new BufferedReader(new FileReader((File)input));
38         else
39         if (input instanceof StringBuffer JavaDoc || input instanceof String JavaDoc)
40             this.reader = new StringReader(input.toString());
41         else
42             throw new IllegalArgumentException JavaDoc("Unknown input object: "+(input != null ? input.getClass().getName() : "null"));
43     }
44
45
46     /** Returns next character or byte from input. Closes input when EOF is reached. */
47     public int read()
48         throws IOException
49     {
50         int i;
51
52         if (readLen > readPos) { // use buffer if buffer is not at end
53
i = buffer[readPos];
54             readPos++;
55             return i;
56         }
57         
58         if (eof)
59             return EOF;
60
61         // read one character from input
62
i = (reader != null) ? reader.read() : inputStream.read();
63         
64         // recognize end of input
65
if (i == -1) {
66             eof = true;
67             
68             try {
69                 if (reader != null)
70                     reader.close();
71                 else
72                     inputStream.close();
73             }
74             catch (IOException e) {
75             }
76         }
77         else {
78             readOffset++;
79             convertInput(i); // input hook for subclasses
80

81             if (buffering) // store character if in buffering state
82
storeRead(i);
83             else
84                 readPos = readLen = 0;
85         }
86         
87         return i;
88     }
89
90
91     /** Read a lookahead character and reset mark after. */
92     public int peek()
93         throws IOException
94     {
95         int mark = getMark();
96         int c = read();
97         setMark(mark);
98         return c;
99     }
100
101     /** Override this to buffer lines or convert any read int. */
102     protected int convertInput(int i) {
103         return i;
104     }
105
106
107     /** Returns the offset of the last scanned char/byte, less or equal the read offset. */
108     public int getScanOffset() {
109         return getReadOffset() - getUnreadLength();
110     }
111
112     /** Returns the offset of the last read char/byte (bigger or equal to scan offset). */
113     public int getReadOffset() {
114         return readOffset;
115     }
116
117
118     /** Get the current read mark and turn on buffering. The mark is a relative offset, not an absolute read position. */
119     public int getMark() {
120         buffering = true;
121         return readPos;
122     }
123     
124     /** Set read position to passed mark. Needed when trying more scan items. This does not turn on buffering like getMark()! */
125     public void setMark(int mark) {
126         readPos = mark;
127     }
128     
129     
130     /** Resolve buffer, skip rest of unread int's to buffer start. */
131     public void resolveBuffer() {
132         buffering = false;
133         
134         if (readLen > readPos) {
135             if (readPos > 0) { // copy unread buffer to bottom
136
int diff = getUnreadLength();
137                 System.arraycopy(buffer, readPos, buffer, 0, diff);
138                 readLen = diff;
139                 readPos = 0;
140             }
141         }
142         else {
143             readPos = readLen = 0;
144         }
145     }
146     
147     
148     // store the int to buffer
149
private void storeRead(int i) {
150         if (buffer == null) // allocate buffer
151
buffer = new int [128];
152         
153         if (readPos == buffer.length) { // reallocate buffer as it is too small
154
//System.err.println("enlarging lexer buffer from "+buffer.length);
155
int [] old = buffer;
156             // the buffer must not be as long as the input, it just serves as lookahead buffer.
157
buffer = new int[old.length * 2];
158             System.arraycopy(old, 0, buffer, 0, old.length);
159         }
160         
161         if (readPos != readLen)
162             throw new IllegalStateException JavaDoc("Can not read to buffer when it was not read empty!");
163             
164         buffer[readPos] = i;
165         readPos++;
166         readLen++;
167     }
168
169
170     /** Returns the part of the buffer that was not yet consumed. */
171     public int [] getUnreadBuffer() {
172         int diff;
173         if (buffer == null || (diff = getUnreadLength()) <= 0)
174             return new int [0];
175         
176         int [] ret = new int[diff];
177         System.arraycopy(buffer, readPos, ret, 0, diff);
178
179         return ret;
180     }
181
182     /** Returns the length that was not yet consumed. */
183     protected int getUnreadLength() {
184         return readLen - readPos;
185     }
186
187 }
Popular Tags