KickJava   Java API By Example, From Geeks To Geeks.

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


1 package fri.patterns.interpreter.parsergenerator.lexer;
2
3 import java.util.*;
4 import java.io.IOException JavaDoc;
5
6 /**
7     Input for text lines. Line number, line position, current line and
8     previous line are available.
9         
10     @author (c) 2002, Fritz Ritzberger
11 */

12
13 class InputText extends Input
14 {
15     private int [] line; // current line buffer
16
private int [] prevLine; // previous line buffer
17
private int prevLength;
18     private boolean wasCr = false; // flag if '\r' occured
19
private int column; // line position
20
private List lineLengths = new ArrayList(); // list of Integer containing line lengths including newline sequence
21
private int [] scanPoint;
22
23
24     InputText(Object JavaDoc input)
25         throws IOException JavaDoc
26     {
27         super(input);
28     }
29
30
31     protected int convertInput(int i) {
32         if (i == '\r') {
33             wasCr = true;
34             newLine();
35         }
36         else {
37             if (i == '\n') {
38                 if (wasCr == false) // on UNIX
39
newLine();
40                 else // on WINDOWS, ignore \n after \r, but adjust previous line length
41
lineLengths.set(
42                             lineLengths.size() - 1,
43                             new Integer JavaDoc( ((Integer JavaDoc) lineLengths.get(lineLengths.size() - 1)).intValue() + 1 )
44                             );
45             }
46             else {
47                 storeRead(i);
48             }
49             wasCr = false;
50         }
51
52         scanPoint = null; // force new scan point calculation
53
return i;
54     }
55
56     private void newLine() {
57         lineLengths.add(new Integer JavaDoc(column + 1)); // line length plus one for the newline, will be adjusted when \r\n
58

59         prevLength = column;
60         column = 0; // reset current line offset
61

62         if (line == null)
63             line = new int[64];
64         
65         if (prevLine == null || prevLine.length < line.length)
66             prevLine = new int [Math.max(line.length, 64)];
67         
68         System.arraycopy(line, 0, prevLine, 0, prevLength);
69     }
70     
71     private void storeRead(int i) {
72         if (line == null) { // allocate buffer
73
line = new int [64];
74         }
75         else
76         if (column == line.length) { // reallocate line buffer
77
int [] old = line;
78             line = new int[old.length * 2];
79             System.arraycopy(old, 0, line, 0, old.length);
80         }
81         
82         line[column] = i;
83         column++;
84     }
85
86
87     /** Returns the current read line number (1-n). This is always bigger equal than scan line. */
88     public int getReadLine() {
89         return lineLengths.size() + 1;
90     }
91
92     /** Returns the current read position (0-n). This is different from scan position. */
93     public int getReadColumn() {
94         return column;
95     }
96
97     /** Returns the current scan line number (1-n). This is always smaller equal than read line. */
98     public int getScanLine() {
99         return calculateScanPoint()[0];
100     }
101
102     /** Returns the current scan position (0-n). This is different from read position. */
103     public int getScanColumn() {
104         return calculateScanPoint()[1];
105     }
106     
107     private int [] calculateScanPoint() { // returns line/column
108
if (scanPoint != null) // use buffered scan pointer when possible, as line/column requests always are coupled
109
return scanPoint;
110             
111         int diff = getReadColumn() - getUnreadLength();
112         if (diff >= 0)
113             return scanPoint = new int[] { getReadLine(), diff };
114         
115         for (int i = lineLengths.size() - 1; i >= 0; i--) { // loop back all lines
116
int len = ((Integer JavaDoc) lineLengths.get(i)).intValue();
117             diff += len;
118             if (diff >= 0)
119                 return scanPoint = new int[] { i + 1, diff };
120         }
121         throw new IllegalStateException JavaDoc("Something went wrong when calculating scan point: "+diff);
122     }
123
124     /** Overridden to resolve scan pointer. Delegates to super. */
125     public int read() throws IOException JavaDoc {
126         scanPoint = null;
127         return super.read();
128     }
129
130     /** Overridden to resolve scan pointer. Delegates to super. */
131     public void setMark(int mark) {
132         scanPoint = null;
133         super.setMark(mark);
134     }
135
136
137     /** Returns a String representing current line up to read position. */
138     public String JavaDoc getLine() {
139         return createLineString(line, column);
140     }
141
142     /** Returns a String representing previous line. */
143     public String JavaDoc getPreviousLine() {
144         return createLineString(prevLine, prevLength);
145     }
146
147     /** Returns all unscanned input in buffer. */
148     public String JavaDoc getUnreadText() {
149         int [] buf = getUnreadBuffer();
150         return createLineString(buf, buf.length);
151     }
152
153     private String JavaDoc createLineString(int [] line, int end) {
154         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
155         for (int i = 0; i < end; i++)
156             sb.append((char) line[i]);
157         return sb.toString();
158     }
159
160 }
Popular Tags