blob: 8cee79df2050978887912ccccc6b452553038c05 [file] [log] [blame]
diegogiorgini@gmail.com2de6d342013-02-16 02:41:45 +00001package [PACKAGE];
2
3import java.io.IOException;
4import [PACKAGE].[LEXER_NAME]Exception;
5
6public class [LEXER_NAME] {
7
8 public static final int
9 TOKEN_EOF = 0, TOKEN_AUX_NOT_FOUND = 1 [TOKENS_CONSTANTS];
10
11 // Human representation of tokens. Useful for debug.
12 // Is possible to convert a TOKEN_CONSTANT in its image through
13 // [LEXER_NAME].tokenKindToString(TOKEN_CONSTANT);
14 private static final String[] tokenImage = {
15 "<EOF>", "<AUX_NOT_FOUND>" [TOKENS_IMAGES]
16 };
17
18 private static final char EOF_CHAR = 4;
19 protected java.io.Reader inputStream;
20 protected int column;
21 protected int line;
22 protected boolean prevCharIsCR;
23 protected boolean prevCharIsLF;
24 protected char[] buffer;
25 protected int bufsize;
26 protected int bufpos;
27 protected int tokenBegin;
28 protected int endOf_USED_Buffer;
29 protected int endOf_UNUSED_Buffer;
30 protected int maxUnusedBufferSize;
31
32// ================================================================================
33// Auxiliary functions. Can parse the tokens used in the grammar as partial/auxiliary
34// ================================================================================
35
36 [LEXER_AUXFUNCTIONS]
37
38// ================================================================================
39// Main method. Return a TOKEN_CONSTANT
40// ================================================================================
41
42 public int next() throws [LEXER_NAME]Exception, IOException{
43 char currentChar = buffer[bufpos];
44 while (currentChar == ' ' || currentChar=='\t' || currentChar == '\n' || currentChar=='\r')
45 currentChar = readNextChar();
46 tokenBegin = bufpos;
47 if (currentChar==EOF_CHAR) return TOKEN_EOF;
48
49 [LEXER_LOGIC]
50 }
51
52// ================================================================================
53// Public interface
54// ================================================================================
55
56 public [LEXER_NAME](java.io.Reader stream) throws IOException{
57 reInit(stream);
58 }
59
60 public void reInit(java.io.Reader stream) throws IOException{
61 done();
62 inputStream = stream;
63 bufsize = 4096;
64 line = 1;
65 column = 0;
66 bufpos = -1;
67 endOf_UNUSED_Buffer = bufsize;
68 endOf_USED_Buffer = 0;
69 prevCharIsCR = false;
70 prevCharIsLF = false;
71 buffer = new char[bufsize];
72 tokenBegin = -1;
73 maxUnusedBufferSize = 4096/2;
74 readNextChar();
75 }
76
77 public String getLastTokenImage() {
78 if (bufpos >= tokenBegin)
79 return new String(buffer, tokenBegin, bufpos - tokenBegin);
80 else
81 return new String(buffer, tokenBegin, bufsize - tokenBegin) +
82 new String(buffer, 0, bufpos);
83 }
84
85 public static String tokenKindToString(int token) {
86 return tokenImage[token];
87 }
88
89 public void done(){
90 buffer = null;
91 }
92
93// ================================================================================
94// Parse error management
95// ================================================================================
96
97 protected int parseError(String reason) throws [LEXER_NAME]Exception {
98 StringBuilder message = new StringBuilder();
99 message.append(reason).append("\n");
100 message.append("Line: ").append(line).append("\n");
101 message.append("Row: ").append(column).append("\n");
102 throw new [LEXER_NAME]Exception(message.toString());
103 }
104
105 protected int parseError(int ... tokens) throws [LEXER_NAME]Exception {
106 StringBuilder message = new StringBuilder();
107 message.append("Error while parsing. ");
108 message.append(" Line: ").append(line);
109 message.append(" Row: ").append(column);
110 message.append(" Expecting:");
111 for (int tokenId : tokens){
112 message.append(" ").append([LEXER_NAME].tokenKindToString(tokenId));
113 }
114 throw new [LEXER_NAME]Exception(message.toString());
115 }
116
117 protected void updateLineColumn(char c){
118 column++;
119
120 if (prevCharIsLF)
121 {
122 prevCharIsLF = false;
123 line += (column = 1);
124 }
125 else if (prevCharIsCR)
126 {
127 prevCharIsCR = false;
128 if (c == '\n')
129 {
130 prevCharIsLF = true;
131 }
132 else
133 {
134 line += (column = 1);
135 }
136 }
137
138 if (c=='\r') {
139 prevCharIsCR = true;
140 } else if(c == '\n') {
141 prevCharIsLF = true;
142 }
143 }
144
145// ================================================================================
146// Read data, buffer management. It uses a circular (and expandable) buffer
147// ================================================================================
148
149 protected char readNextChar() throws IOException {
150 if (++bufpos >= endOf_USED_Buffer)
151 fillBuff();
152 char c = buffer[bufpos];
153 updateLineColumn(c);
154 return c;
155 }
156
157 protected boolean fillBuff() throws IOException {
158 if (endOf_UNUSED_Buffer == endOf_USED_Buffer) // If no more unused buffer space
159 {
160 if (endOf_UNUSED_Buffer == bufsize) // -- If the previous unused space was
161 { // -- at the end of the buffer
162 if (tokenBegin > maxUnusedBufferSize) // -- -- If the first N bytes before
163 { // the current token are enough
164 bufpos = endOf_USED_Buffer = 0; // -- -- -- setup buffer to use that fragment
165 endOf_UNUSED_Buffer = tokenBegin;
166 }
167 else if (tokenBegin < 0) // -- -- If no token yet
168 bufpos = endOf_USED_Buffer = 0; // -- -- -- reuse the whole buffer
169 else
170 ExpandBuff(false); // -- -- Otherwise expand buffer after its end
171 }
172 else if (endOf_UNUSED_Buffer > tokenBegin) // If the endOf_UNUSED_Buffer is after the token
173 endOf_UNUSED_Buffer = bufsize; // -- set endOf_UNUSED_Buffer to the end of the buffer
174 else if ((tokenBegin - endOf_UNUSED_Buffer) < maxUnusedBufferSize)
175 { // If between endOf_UNUSED_Buffer and the token
176 ExpandBuff(true); // there is NOT enough space expand the buffer
177 } // reorganizing it
178 else
179 endOf_UNUSED_Buffer = tokenBegin; // Otherwise there is enough space at the start
180 } // so we set the buffer to use that fragment
181 int i;
182 if ((i = inputStream.read(buffer, endOf_USED_Buffer, endOf_UNUSED_Buffer - endOf_USED_Buffer)) == -1)
183 {
184 inputStream.close();
185 buffer[endOf_USED_Buffer]=(char)EOF_CHAR;
186 endOf_USED_Buffer++;
187 return false;
188 }
189 else
190 endOf_USED_Buffer += i;
191 return true;
192 }
193
194
195 protected void ExpandBuff(boolean wrapAround)
196 {
197 char[] newbuffer = new char[bufsize + maxUnusedBufferSize];
198
199 try {
200 if (wrapAround) {
201 System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
202 System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
203 buffer = newbuffer;
204 endOf_USED_Buffer = (bufpos += (bufsize - tokenBegin));
205 }
206 else {
207 System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
208 buffer = newbuffer;
209 endOf_USED_Buffer = (bufpos -= tokenBegin);
210 }
211 } catch (Throwable t) {
212 throw new Error(t.getMessage());
213 }
214
215 bufsize += maxUnusedBufferSize;
216 endOf_UNUSED_Buffer = bufsize;
217 tokenBegin = 0;
218 }
219}