Package: BacktrackInputReader$ReaderType

BacktrackInputReader$ReaderType

nameinstructionbranchcomplexitylinemethod
static {...}
M: 44 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: *
3: *        Copyright (c) 2008 Fujitsu Services Ltd.
4: *
5: *        Author: Nick Battle
6: *
7: *        This file is part of VDMJ.
8: *
9: *        VDMJ is free software: you can redistribute it and/or modify
10: *        it under the terms of the GNU General Public License as published by
11: *        the Free Software Foundation, either version 3 of the License, or
12: *        (at your option) any later version.
13: *
14: *        VDMJ is distributed in the hope that it will be useful,
15: *        but WITHOUT ANY WARRANTY; without even the implied warranty of
16: *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: *        GNU General Public License for more details.
18: *
19: *        You should have received a copy of the GNU General Public License
20: *        along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
21: *
22: ******************************************************************************/
23:
24: package org.overture.parser.lex;
25:
26: import java.io.ByteArrayInputStream;
27: import java.io.File;
28: import java.io.FileInputStream;
29: import java.io.IOException;
30: import java.io.InputStreamReader;
31: import java.io.Reader;
32: import java.nio.charset.Charset;
33: import java.util.Arrays;
34: import java.util.Stack;
35:
36: import org.overture.ast.messages.InternalException;
37:
38: /**
39: * A class to allow arbitrary checkpoints and backtracking while parsing a file.
40: */
41:
42: public class BacktrackInputReader extends Reader
43: {
44:         /**
45:          * The different types of reader that may be obtained from a {@link BacktrackInputReader}
46:          *
47:          * @author pvj
48:          */
49:         public enum ReaderType
50:         {
51:                 Doc, Docx, Odf, Latex
52:         };
53:
54:         /**
55:          * Cached empty array for reader data
56:          */
57:         private static final char[] EMPTY_DATA = new char[] {};
58:
59:         /** A stack of position markers for popping. */
60:         private Stack<Integer> stack = new Stack<Integer>();
61:
62:         /** The characters from the file. */
63:         private final char[] data;
64:
65:         /** The current read position. */
66:         private int pos = 0;
67:
68:         /** The total number of characters in the file. */
69:         private int max = 0;
70:
71:         /**
72:          * Create an object to read the file name passed with the given charset.
73:          *
74:          * @param file
75:          * The filename to open
76:          * @param charset
77:          */
78:
79:         public BacktrackInputReader(File file, String charset)
80:         {
81:                 try
82:                 {
83:                         InputStreamReader isr = readerFactory(file, charset);
84:                         char[] buffer = new char[readerLength(file, isr)];
85:                         max = isr.read(buffer);
86:                         data = Arrays.copyOf(buffer, max);
87:                         pos = 0;
88:                         isr.close();
89:                 } catch (IOException e)
90:                 {
91:                         throw new InternalException(0, e.getMessage());
92:                 }
93:         }
94:
95:         /**
96:          * Create an object to read the file name passed with the default charset.
97:          *
98:          * @param file
99:          * The filename to open
100:          */
101:
102:         public BacktrackInputReader(File file)
103:         {
104:                 this(file, Charset.defaultCharset().name());
105:         }
106:
107:         /**
108:          * Create an object to read the string passed. This is used in the interpreter to parse expressions typed in.
109:          *
110:          * @param expression
111:          * @param charset
112:          */
113:
114:         public BacktrackInputReader(String expression, String charset)
115:         {
116:                 char[] buf = EMPTY_DATA;
117:                 try
118:                 {
119:                         ByteArrayInputStream is = new ByteArrayInputStream(expression.getBytes(charset));
120:
121:                         InputStreamReader isr = new LatexStreamReader(is, charset);
122:
123:                         buf = new char[expression.length() + 1];
124:                         max = isr.read(buf);
125:                         pos = 0;
126:
127:                         isr.close();
128:                         is.close();
129:                 } catch (IOException e)
130:                 {
131:                         // This can never really happen...
132:                 } finally
133:                 {
134:                         data = buf;
135:                 }
136:         }
137:
138:         /**
139:          * Create an object to read the string passed. This is used in the interpreter to parse expressions typed in.
140:          *
141:          * @param expression
142:          * @param charset
143:          * @param file
144:          * @param streamReaderType
145:          */
146:         public BacktrackInputReader(String expression, String charset, File file,
147:                         ReaderType streamReaderType)
148:         {
149:                 char[] buf = EMPTY_DATA;
150:                 try
151:                 {
152:                         if (expression.contains("\r\n"))
153:                         {
154:                                 expression = expression.replace("\r\n", " \n");
155:                         }
156:
157:                         ByteArrayInputStream is = new ByteArrayInputStream(expression.getBytes(charset));
158:
159:                         InputStreamReader isr = null;
160:
161:                         switch (streamReaderType)
162:                         {
163:                                 case Doc:
164:                                         isr = new DocStreamReader(new FileInputStream(file), charset);
165:                                         break;
166:                                 case Docx:
167:                                         isr = new DocxStreamReader(new FileInputStream(file));
168:                                         break;
169:                                 case Odf:
170:                                         isr = new ODFStreamReader(new FileInputStream(file));
171:                                         break;
172:                                 case Latex:
173:                                 default:
174:                                         isr = new LatexStreamReader(is, charset);
175:                                         break;
176:                         }
177:
178:                         if (!expression.contains("\r\n"))
179:                         {
180:                                 expression = expression.replace("\n", " \n");
181:                         }
182:
183:                         buf = new char[expression.length() + 1];
184:                         max = isr.read(buf);
185:                         pos = 0;
186:
187:                         isr.close();
188:                         is.close();
189:                 } catch (IOException e)
190:                 {
191:                         e.printStackTrace();
192:                         // This can never really happen...
193:                 } finally
194:                 {
195:                         data = buf;
196:                 }
197:         }
198:
199:         /**
200:          * Create an InputStreamReader from a File, depending on the filename.
201:          *
202:          * @param file
203:          * @param charset
204:          * @return
205:          * @throws IOException
206:          */
207:
208:         public static InputStreamReader readerFactory(File file, String charset)
209:                         throws IOException
210:         {
211:                 String name = file.getName();
212:
213:                 if (name.toLowerCase().endsWith(".doc"))
214:                 {
215:                         return new DocStreamReader(new FileInputStream(file), charset);
216:                 } else if (name.toLowerCase().endsWith(".docx"))
217:                 {
218:                         return new DocxStreamReader(new FileInputStream(file));
219:                 } else if (name.toLowerCase().endsWith(".odt"))
220:                 {
221:                         return new ODFStreamReader(new FileInputStream(file));
222:                 } else
223:                 {
224:                         return new LatexStreamReader(new FileInputStream(file), charset);
225:                 }
226:         }
227:
228:         /**
229:          * Calculate the length to allocate for a given file/stream.
230:          */
231:
232:         private int readerLength(File file, InputStreamReader isr)
233:         {
234:                 String name = file.getName();
235:
236:                 if (name.endsWith(".docx"))
237:                 {
238:                         return ((DocxStreamReader) isr).length();
239:                 } else if (name.endsWith(".odt"))
240:                 {
241:                         return ((ODFStreamReader) isr).length();
242:                 } else
243:                 {
244:                         return (int) (file.length() + 1);
245:                 }
246:         }
247:
248:         /**
249:          * Create an object to read the string passed with the default charset.
250:          *
251:          * @param expression
252:          */
253:
254:         public BacktrackInputReader(String expression)
255:         {
256:                 this(expression, Charset.defaultCharset().name());
257:         }
258:
259:         /**
260:          * Push the current location to permit backtracking.
261:          */
262:
263:         public void push()
264:         {
265:                 stack.push(pos);
266:         }
267:
268:         /**
269:          * Pop the last location, but do not backtrack to it. This is used when the parser reached a point where a potential
270:          * ambiguity has been resolved, and it knows that it will never need to backtrack.
271:          */
272:
273:         public void unpush()
274:         {
275:                 stack.pop(); // don't set pos though
276:         }
277:
278:         /**
279:          * Pop the last location and reposition the stream at that position. The state of the stream is such that the next
280:          * read operation will return the same character that would have been read immediately after the push() operation
281:          * that saved the position.
282:          */
283:
284:         public void pop()
285:         {
286:                 pos = stack.pop();
287:         }
288:
289:         /**
290:          * Read one character.
291:          *
292:          * @return
293:          */
294:
295:         public char readCh()
296:         {
297:                 return data.length <= pos || pos == max ? (char) -1 : data[pos++];
298:         }
299:
300:         /**
301:          * Read characters into the array passed.
302:          */
303:
304:         @Override
305:         public int read(char[] cbuf, int off, int len)
306:         {
307:                 int n = 0;
308:
309:                 while (pos != max && n < len)
310:                 {
311:                         cbuf[off + n++] = data[pos++];
312:                 }
313:
314:                 return n == 0 ? -1 : n;
315:         }
316:
317:         /**
318:          * Close the input stream.
319:          */
320:
321:         @Override
322:         public void close()
323:         {
324:                 return; // Stream was closed at the start anyway.
325:         }
326:
327:         public int getCurrentRawReadOffset()
328:         {
329:                 return pos;
330:         }
331: }