1 package org.simantics.scl.compiler.internal.parsing.utils;
3 import java.io.IOException;
6 import org.simantics.scl.compiler.errors.Locations;
9 * A wrapper to reader that remembers the last characters
10 * read and line numbers.
12 * @author Hannu Niemistö
14 public class MemoReader extends Reader {
17 char[] buffer = new char[80];
18 int absoluteBegin = 0;
23 int[] lineLocations = new int[8];
26 public MemoReader(Reader base) {
31 private int findLineLocationArrayOffset(int location) {
33 int h = lineLocationsPos;
36 int loc = lineLocations[c];
45 private void addLine(int location) {
46 if(lineLocationsPos == lineLocations.length) {
47 int p = findLineLocationArrayOffset(absoluteBegin);
48 if(p*2 >= lineLocationsPos)
49 System.arraycopy(lineLocations, p, lineLocations, 0, lineLocationsPos-p);
51 int[] newLineLocations = new int[lineLocations.length*2];
52 System.arraycopy(lineLocations, p, newLineLocations, 0, lineLocationsPos-p);
53 lineLocations = newLineLocations;
55 lineLocationsPos -= p;
58 lineLocations[lineLocationsPos++] = location;
61 public String locationToString(int location) {
62 int lOffset = findLineLocationArrayOffset(location);
63 int row = lOffset + firstLine;
64 int column = location + 1 - lineLocations[lOffset];
65 return row + ":" + column;
68 public String locationToString(long location) {
69 if(location == Locations.NO_LOCATION)
72 return locationToString(Locations.beginOf(location))
74 locationToString(Locations.endOf(location))
78 public String locationUnderlining(long coupledLocation) {
84 int location = Locations.beginOf(coupledLocation);
85 int lOffset = findLineLocationArrayOffset(location);
86 beginRow = lOffset + firstLine;
87 beginColumn = location - lineLocations[lOffset] + 2;
90 int location = Locations.endOf(coupledLocation);
91 int lOffset = findLineLocationArrayOffset(location);
92 endRow = lOffset + firstLine;
93 endColumn = location - lineLocations[lOffset] + 2;
95 StringBuilder b = new StringBuilder();
96 while(b.length() < beginColumn)
98 if(beginRow == endRow) {
99 int end = Math.max(endColumn, beginColumn+1);
100 while(b.length() < end)
105 b.append(" (").append(beginRow).append(':').append(beginColumn).append('-')
106 .append(endRow).append(':').append(endColumn).append(')');
110 private void ensureCapacity(int count) {
111 if(end + count > buffer.length) {
112 if(end - begin + count <= buffer.length) {
113 System.arraycopy(buffer, begin, buffer, 0, end-begin);
118 char[] newBuffer = new char[Math.max(buffer.length*2, end+count)];
119 System.arraycopy(buffer, begin, newBuffer, begin, end-begin);
126 public int read(char[] cbuf, int off, int len) throws IOException {
127 int count = base.read(cbuf, off, len);
129 for(int i=0;i<count;++i)
130 if(cbuf[off+i] == '\n')
132 ensureCapacity(count);
133 System.arraycopy(cbuf, off, buffer, end, count);
140 public int read() throws IOException {
141 int result = base.read();
144 buffer[end++] = (char)result;
151 public String extractString(long location) {
152 int requestedBegin = Locations.beginOf(location);
153 int requestedEnd = Locations.endOf(location);
154 if(requestedBegin < absoluteBegin)
155 throw new IllegalArgumentException();
156 return new String(buffer,
157 begin + requestedBegin - absoluteBegin,
158 requestedEnd-requestedBegin);
161 public void forgetEverythingBefore(int location) {
162 begin += location-absoluteBegin;
163 absoluteBegin = location;
167 public void close() throws IOException {
171 public String getLastCommand() {
175 if(c < 0 || c == '\n')
177 } catch (IOException e) {
182 if(buffer[p] == '\n')
184 return new String(buffer, p, end-p);