1
2 package sl;
3
4 /***
5 * An implementation of interface CharStream, where the stream is assumed to
6 * contain only ASCII characters (with java-like unicode escape processing).
7 */
8
9 public final class ASCII_UCodeESC_CharStream
10 {
11 public static final boolean staticFlag = false;
12 static final int hexval(char c) throws java.io.IOException {
13 switch(c)
14 {
15 case '0' :
16 return 0;
17 case '1' :
18 return 1;
19 case '2' :
20 return 2;
21 case '3' :
22 return 3;
23 case '4' :
24 return 4;
25 case '5' :
26 return 5;
27 case '6' :
28 return 6;
29 case '7' :
30 return 7;
31 case '8' :
32 return 8;
33 case '9' :
34 return 9;
35
36 case 'a' :
37 case 'A' :
38 return 10;
39 case 'b' :
40 case 'B' :
41 return 11;
42 case 'c' :
43 case 'C' :
44 return 12;
45 case 'd' :
46 case 'D' :
47 return 13;
48 case 'e' :
49 case 'E' :
50 return 14;
51 case 'f' :
52 case 'F' :
53 return 15;
54 }
55
56 throw new java.io.IOException();
57 }
58
59 public int bufpos = -1;
60 int bufsize;
61 int available;
62 int tokenBegin;
63 private int bufline[];
64 private int bufcolumn[];
65
66 private int column = 0;
67 private int line = 1;
68
69 private java.io.Reader inputStream;
70
71 private boolean prevCharIsCR = false;
72 private boolean prevCharIsLF = false;
73
74 private char[] nextCharBuf;
75 private char[] buffer;
76 private int maxNextCharInd = 0;
77 private int nextCharInd = -1;
78 private int inBuf = 0;
79
80 private final void ExpandBuff(boolean wrapAround)
81 {
82 char[] newbuffer = new char[bufsize + 2048];
83 int newbufline[] = new int[bufsize + 2048];
84 int newbufcolumn[] = new int[bufsize + 2048];
85
86 try
87 {
88 if (wrapAround)
89 {
90 System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
91 System.arraycopy(buffer, 0, newbuffer,
92 bufsize - tokenBegin, bufpos);
93 buffer = newbuffer;
94
95 System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
96 System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
97 bufline = newbufline;
98
99 System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
100 System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
101 bufcolumn = newbufcolumn;
102
103 bufpos += (bufsize - tokenBegin);
104 }
105 else
106 {
107 System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
108 buffer = newbuffer;
109
110 System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
111 bufline = newbufline;
112
113 System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
114 bufcolumn = newbufcolumn;
115
116 bufpos -= tokenBegin;
117 }
118 }
119 catch (Throwable t)
120 {
121 throw new Error(t.getMessage());
122 }
123
124 available = (bufsize += 2048);
125 tokenBegin = 0;
126 }
127
128 private final void FillBuff() throws java.io.IOException
129 {
130 int i;
131 if (maxNextCharInd == 4096)
132 maxNextCharInd = nextCharInd = 0;
133
134 try {
135 if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
136 4096 - maxNextCharInd)) == -1)
137 {
138 inputStream.close();
139 throw new java.io.IOException();
140 }
141 else
142 maxNextCharInd += i;
143 return;
144 }
145 catch(java.io.IOException e) {
146 if (bufpos != 0)
147 {
148 --bufpos;
149 backup(0);
150 }
151 else
152 {
153 bufline[bufpos] = line;
154 bufcolumn[bufpos] = column;
155 }
156 throw e;
157 }
158 }
159
160 private final char ReadByte() throws java.io.IOException
161 {
162 if (++nextCharInd >= maxNextCharInd)
163 FillBuff();
164
165 return nextCharBuf[nextCharInd];
166 }
167
168 public final char BeginToken() throws java.io.IOException
169 {
170 if (inBuf > 0)
171 {
172 --inBuf;
173 return buffer[tokenBegin = (bufpos == bufsize - 1) ? (bufpos = 0)
174 : ++bufpos];
175 }
176
177 tokenBegin = 0;
178 bufpos = -1;
179
180 return readChar();
181 }
182
183 private final void AdjustBuffSize()
184 {
185 if (available == bufsize)
186 {
187 if (tokenBegin > 2048)
188 {
189 bufpos = 0;
190 available = tokenBegin;
191 }
192 else
193 ExpandBuff(false);
194 }
195 else if (available > tokenBegin)
196 available = bufsize;
197 else if ((tokenBegin - available) < 2048)
198 ExpandBuff(true);
199 else
200 available = tokenBegin;
201 }
202
203 private final void UpdateLineColumn(char c)
204 {
205 column++;
206
207 if (prevCharIsLF)
208 {
209 prevCharIsLF = false;
210 line += (column = 1);
211 }
212 else if (prevCharIsCR)
213 {
214 prevCharIsCR = false;
215 if (c == '\n')
216 {
217 prevCharIsLF = true;
218 }
219 else
220 line += (column = 1);
221 }
222
223 switch (c)
224 {
225 case '\r' :
226 prevCharIsCR = true;
227 break;
228 case '\n' :
229 prevCharIsLF = true;
230 break;
231 case '\t' :
232 column--;
233 column += (8 - (column & 07));
234 break;
235 default :
236 break;
237 }
238
239 bufline[bufpos] = line;
240 bufcolumn[bufpos] = column;
241 }
242
243 public final char readChar() throws java.io.IOException
244 {
245 if (inBuf > 0)
246 {
247 --inBuf;
248 return buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos];
249 }
250
251 char c;
252
253 if (++bufpos == available)
254 AdjustBuffSize();
255
256 if (((buffer[bufpos] = c = (char)((char)0xff & ReadByte())) == '//'))
257 {
258 UpdateLineColumn(c);
259
260 int backSlashCnt = 1;
261
262 for (;;)
263 {
264 if (++bufpos == available)
265 AdjustBuffSize();
266
267 try
268 {
269 if ((buffer[bufpos] = c = (char)((char)0xff & ReadByte())) != '//')
270 {
271 UpdateLineColumn(c);
272
273 if ((c == 'u') && ((backSlashCnt & 1) == 1))
274 {
275 if (--bufpos < 0)
276 bufpos = bufsize - 1;
277
278 break;
279 }
280
281 backup(backSlashCnt);
282 return '//';
283 }
284 }
285 catch(java.io.IOException e)
286 {
287 if (backSlashCnt > 1)
288 backup(backSlashCnt);
289
290 return '//';
291 }
292
293 UpdateLineColumn(c);
294 backSlashCnt++;
295 }
296
297
298 try
299 {
300 while ((c = (char)((char)0xff & ReadByte())) == 'u')
301 ++column;
302
303 buffer[bufpos] = c = (char)(hexval(c) << 12 |
304 hexval((char)((char)0xff & ReadByte())) << 8 |
305 hexval((char)((char)0xff & ReadByte())) << 4 |
306 hexval((char)((char)0xff & ReadByte())));
307
308 column += 4;
309 }
310 catch(java.io.IOException e)
311 {
312 throw new Error("Invalid escape character at line " + line +
313 " column " + column + ".");
314 }
315
316 if (backSlashCnt == 1)
317 return c;
318 else
319 {
320 backup(backSlashCnt - 1);
321 return '//';
322 }
323 }
324 else
325 {
326 UpdateLineColumn(c);
327 return (c);
328 }
329 }
330
331 /***
332 * @deprecated
333 * @see #getEndColumn
334 */
335
336 public final int getColumn() {
337 return bufcolumn[bufpos];
338 }
339
340 /***
341 * @deprecated
342 * @see #getEndLine
343 */
344
345 public final int getLine() {
346 return bufline[bufpos];
347 }
348
349 public final int getEndColumn() {
350 return bufcolumn[bufpos];
351 }
352
353 public final int getEndLine() {
354 return bufline[bufpos];
355 }
356
357 public final int getBeginColumn() {
358 return bufcolumn[tokenBegin];
359 }
360
361 public final int getBeginLine() {
362 return bufline[tokenBegin];
363 }
364
365 public final void backup(int amount) {
366
367 inBuf += amount;
368 if ((bufpos -= amount) < 0)
369 bufpos += bufsize;
370 }
371
372 public ASCII_UCodeESC_CharStream(java.io.Reader dstream,
373 int startline, int startcolumn, int buffersize)
374 {
375 inputStream = dstream;
376 line = startline;
377 column = startcolumn - 1;
378
379 available = bufsize = buffersize;
380 buffer = new char[buffersize];
381 bufline = new int[buffersize];
382 bufcolumn = new int[buffersize];
383 nextCharBuf = new char[4096];
384 }
385
386 public ASCII_UCodeESC_CharStream(java.io.Reader dstream,
387 int startline, int startcolumn)
388 {
389 this(dstream, startline, startcolumn, 4096);
390 }
391 public void ReInit(java.io.Reader dstream,
392 int startline, int startcolumn, int buffersize)
393 {
394 inputStream = dstream;
395 line = startline;
396 column = startcolumn - 1;
397
398 if (buffer == null || buffersize != buffer.length)
399 {
400 available = bufsize = buffersize;
401 buffer = new char[buffersize];
402 bufline = new int[buffersize];
403 bufcolumn = new int[buffersize];
404 nextCharBuf = new char[4096];
405 }
406 prevCharIsLF = prevCharIsCR = false;
407 tokenBegin = inBuf = maxNextCharInd = 0;
408 nextCharInd = bufpos = -1;
409 }
410
411 public void ReInit(java.io.Reader dstream,
412 int startline, int startcolumn)
413 {
414 ReInit(dstream, startline, startcolumn, 4096);
415 }
416 public ASCII_UCodeESC_CharStream(java.io.InputStream dstream, int startline,
417 int startcolumn, int buffersize)
418 {
419 this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
420 }
421
422 public ASCII_UCodeESC_CharStream(java.io.InputStream dstream, int startline,
423 int startcolumn)
424 {
425 this(dstream, startline, startcolumn, 4096);
426 }
427
428 public void ReInit(java.io.InputStream dstream, int startline,
429 int startcolumn, int buffersize)
430 {
431 ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
432 }
433 public void ReInit(java.io.InputStream dstream, int startline,
434 int startcolumn)
435 {
436 ReInit(dstream, startline, startcolumn, 4096);
437 }
438
439 public final String GetImage()
440 {
441 if (bufpos >= tokenBegin)
442 return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
443 else
444 return new String(buffer, tokenBegin, bufsize - tokenBegin) +
445 new String(buffer, 0, bufpos + 1);
446 }
447
448 public final char[] GetSuffix(int len)
449 {
450 char[] ret = new char[len];
451
452 if ((bufpos + 1) >= len)
453 System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
454 else
455 {
456 System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
457 len - bufpos - 1);
458 System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
459 }
460
461 return ret;
462 }
463
464 public void Done()
465 {
466 nextCharBuf = null;
467 buffer = null;
468 bufline = null;
469 bufcolumn = null;
470 }
471
472 /***
473 * Method to adjust line and column numbers for the start of a token.<BR>
474 */
475 public void adjustBeginLineColumn(int newLine, int newCol)
476 {
477 int start = tokenBegin;
478 int len;
479
480 if (bufpos >= tokenBegin)
481 {
482 len = bufpos - tokenBegin + inBuf + 1;
483 }
484 else
485 {
486 len = bufsize - tokenBegin + bufpos + 1 + inBuf;
487 }
488
489 int i = 0, j = 0, k = 0;
490 int nextColDiff = 0, columnDiff = 0;
491
492 while (i < len &&
493 bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
494 {
495 bufline[j] = newLine;
496 nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
497 bufcolumn[j] = newCol + columnDiff;
498 columnDiff = nextColDiff;
499 i++;
500 }
501
502 if (i < len)
503 {
504 bufline[j] = newLine++;
505 bufcolumn[j] = newCol + columnDiff;
506
507 while (i++ < len)
508 {
509 if (bufline[j = start % bufsize] != bufline[++start % bufsize])
510 bufline[j] = newLine++;
511 else
512 bufline[j] = newLine;
513 }
514 }
515
516 line = bufline[j];
517 column = bufcolumn[j];
518 }
519
520 }