001: package murlen.util.fscript;
002:
003: import java.util.ArrayList;
004: import java.io.Reader;
005: import java.io.BufferedReader;
006: import java.io.IOException;
007:
008: /**
009: * <b>LineLoader - used by FScript to load source text</b>
010: * <p>
011: * <I>Copyright (C) 2000 murlen.</I></p>
012: * <p>
013: * This library is free software; you can redistribute it and/or
014: * modify it under the terms of the GNU Library General Public
015: * License as published by the Free Software Foundation; either
016: * version 2 of the License, or (at your option) any later version.</p>
017: * <p>
018: * This library is distributed in the hope that it will be useful,
019: * but WITHOUT ANY WARRANTY; without even the implied warranty of
020: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
021: * Library General Public License for more details.</p>
022: *
023: * <p>You should have received a copy of the GNU Library General Public
024: * License along with this library; if not, write to the Free
025: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA </p>
026: * @author murlen
027: * @author Joachim Van der Auwera
028: * @version 1.12
029: *
030: * changes by Joachim Van der Auwera
031: * 20.08.2001
032: * - getLine added
033: * - setCurLine test was wrong, allowed setting line one too far
034: * 02.08.2002
035: * - allow commands to be split over multiple line by using the "..." continuation mark
036: * 07.10.2002
037: * - do not join lines when the ... is at the end of a comment
038: * 08.11.2002 but do join them when the hash is inside a quote (and does not indicate a comment)
039: * 17.09.2003 moved checking for mismatched quotes and brackets here
040: * 24.11.2003 (jvda) use char[] instead of String to store lines
041: */
042:
043: final class LineLoader {
044:
045: ArrayList lines;
046: private String contLine; // previous line if it ended with "..." (but without the "...")
047: private char[] emptyLine = new char[0];
048:
049: int curLine;
050: String forError;
051:
052: /**
053: *Constructor */
054: LineLoader() {
055:
056: lines = new ArrayList(200);
057: curLine = 0;
058: }
059:
060: /**
061: * load with script from InputStreamReader
062: * @param is - the input stream to read from
063: */
064: final void load(Reader is) throws IOException {
065:
066: BufferedReader in = new BufferedReader(is);
067: String s;
068: s = in.readLine();
069:
070: while (s != null) {
071: addLine(s);
072: s = in.readLine();
073: }
074:
075: in.close();
076:
077: curLine = 0;
078: }
079:
080: /**
081: * resets the LineLoader */
082: final void reset() {
083: lines = new ArrayList(200);
084: curLine = 0;
085: }
086:
087: /**
088: * method to incrementally add lines to buffer
089: * @param s the line to load */
090: final void addLine(String s) {
091: if (!s.trim().equals("")) {
092: if (s.endsWith("...") && !hasComment(s)) {
093: if (contLine != null) {
094: contLine += s.substring(0, s.length() - 3);
095: } else {
096: contLine = s.substring(0, s.length() - 3);
097: }
098: } else {
099: if (contLine != null) {
100: contLine += s;
101: } else {
102: contLine = s;
103: }
104: char line[] = contLine.toCharArray();
105: checkLine(line);
106: lines.add(line);
107: contLine = null;
108: }
109: } else {
110: //need to add blank lines to keep error msg lines
111: //in sync with file lines.
112: lines.add(emptyLine);
113: }
114: }
115:
116: private boolean hasComment(String s) {
117: boolean cont;
118: int hash, quote;
119: while (!s.equals("")) {
120: hash = s.indexOf('#');
121: if (hash == -1)
122: return false;
123: quote = s.indexOf('\"');
124: if (quote == -1 || hash < quote)
125: return true;
126: // hash may be inside a string, so remove quoted part
127: cont = true;
128: while (cont) {
129: s = s.substring(quote + 1);
130: quote = s.indexOf('\"');
131: if (quote == 0 || s.charAt(quote - 1) != '\\')
132: cont = false;
133: }
134: s = s.substring(quote + 1);
135: }
136: return false;
137: }
138:
139: /**
140: * Sets the current execution line
141: * @param n the line number */
142: final void setCurLine(int n) {
143: if (n > lines.size()) {
144: n = lines.size() - 1;
145: } else if (n < 0) {
146: n = 0;
147: }
148:
149: curLine = n;
150: }
151:
152: /**
153: * Returns the current execution line */
154: final int getCurLine() {
155: return curLine;
156: }
157:
158: /**
159: * Returns the total number of lines in buffer */
160: final int lineCount() {
161: return lines.size();
162: }
163:
164: /**
165: * Returns the text of the current line */
166: final char[] getLine() {
167: return (char[]) lines.get(curLine);
168: }
169:
170: /**
171: * Returns the text of the current line as a String */
172: final String getLineAsString() {
173: if (curLine == -1)
174: return forError;
175: return new String((char[]) lines.get(curLine));
176: }
177:
178: /**
179: *Returns the text of the requested line*/
180: final char[] getLine(int n) {
181: if (n < 0 || n >= lines.size())
182: return emptyLine;
183: return (char[]) lines.get(n);
184: }
185:
186: /**
187: * Returns the text of the requested line as a String */
188: final String getLineAsString(int n) {
189: if (n < 0 || n >= lines.size())
190: return "";
191: return new String((char[]) lines.get(n));
192: }
193:
194: /**
195: * Checks line for correctly formed ( ) and "
196: */
197: static void checkLine(char chars[]) {
198: boolean inQuotes = false;
199: int brCount = 0;
200: int n;
201:
202: if (chars != null) {
203: for (n = 0; n < chars.length; n++) {
204: if (chars[n] == '#' && !inQuotes) {
205: n = chars.length;
206: } else {
207: if (inQuotes) {
208: if (chars[n] == '"') {
209: if (n >= 1) {
210: if (chars[n - 1] != '\\') {
211: inQuotes = false;
212: }
213: }
214: }
215: } else {
216: if (chars[n] == '(') {
217: brCount++;
218: } else if (chars[n] == ')') {
219: brCount--;
220: } else if (chars[n] == '"') {
221: if (n >= 1) {
222: if (chars[n - 1] != '\\') {
223: inQuotes = true;
224: }
225: }
226: }
227: }
228: }
229: }
230:
231: if (inQuotes) {
232: throw new RuntimeException("Mismatched quotes\n"
233: + new String(chars));
234: }
235: if (brCount != 0) {
236: throw new RuntimeException("Mismatched brackets\n"
237: + new String(chars));
238: }
239: }
240:
241: }
242:
243: }
|