001: /* ****************************************************************************
002: * AttributeStream.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: /*
011: * This is a ripoff of JavaCC's SimpleCharStream, which I would have
012: * subclassed if it were not declared final, or I would have used
013: * directly, if it admitted that it implemented CharStream. Perhaps a
014: * future version of JavaCC will make this unnecessary.
015: */
016:
017: package org.openlaszlo.compiler;
018:
019: import org.openlaszlo.css.CharStream;
020: import java.io.*;
021: import org.jdom.Element;
022:
023: /* START JavaCC SimpleCharStream */
024:
025: /**
026: * An implementation of interface CharStream, where the stream is assumed to
027: * contain only ASCII characters (without unicode processing).
028: */
029:
030: class SimpleCharStream implements CharStream {
031: public static final boolean staticFlag = false;
032: int bufsize;
033: int available;
034: int tokenBegin;
035: public int bufpos = -1;
036: private int bufline[];
037: private int bufcolumn[];
038:
039: private int column = 0;
040: private int line = 1;
041:
042: private boolean prevCharIsCR = false;
043: private boolean prevCharIsLF = false;
044:
045: private java.io.Reader inputStream;
046:
047: private char[] buffer;
048: private int maxNextCharInd = 0;
049: private int inBuf = 0;
050:
051: private final void ExpandBuff(boolean wrapAround) {
052: char[] newbuffer = new char[bufsize + 2048];
053: int newbufline[] = new int[bufsize + 2048];
054: int newbufcolumn[] = new int[bufsize + 2048];
055:
056: try {
057: if (wrapAround) {
058: System.arraycopy(buffer, tokenBegin, newbuffer, 0,
059: bufsize - tokenBegin);
060: System.arraycopy(buffer, 0, newbuffer, bufsize
061: - tokenBegin, bufpos);
062: buffer = newbuffer;
063:
064: System.arraycopy(bufline, tokenBegin, newbufline, 0,
065: bufsize - tokenBegin);
066: System.arraycopy(bufline, 0, newbufline, bufsize
067: - tokenBegin, bufpos);
068: bufline = newbufline;
069:
070: System.arraycopy(bufcolumn, tokenBegin, newbufcolumn,
071: 0, bufsize - tokenBegin);
072: System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize
073: - tokenBegin, bufpos);
074: bufcolumn = newbufcolumn;
075:
076: maxNextCharInd = (bufpos += (bufsize - tokenBegin));
077: } else {
078: System.arraycopy(buffer, tokenBegin, newbuffer, 0,
079: bufsize - tokenBegin);
080: buffer = newbuffer;
081:
082: System.arraycopy(bufline, tokenBegin, newbufline, 0,
083: bufsize - tokenBegin);
084: bufline = newbufline;
085:
086: System.arraycopy(bufcolumn, tokenBegin, newbufcolumn,
087: 0, bufsize - tokenBegin);
088: bufcolumn = newbufcolumn;
089:
090: maxNextCharInd = (bufpos -= tokenBegin);
091: }
092: } catch (Throwable t) {
093: throw new Error(t.getMessage());
094: }
095:
096: bufsize += 2048;
097: available = bufsize;
098: tokenBegin = 0;
099: }
100:
101: private final void FillBuff() throws java.io.IOException {
102: if (maxNextCharInd == available) {
103: if (available == bufsize) {
104: if (tokenBegin > 2048) {
105: bufpos = maxNextCharInd = 0;
106: available = tokenBegin;
107: } else if (tokenBegin < 0)
108: bufpos = maxNextCharInd = 0;
109: else
110: ExpandBuff(false);
111: } else if (available > tokenBegin)
112: available = bufsize;
113: else if ((tokenBegin - available) < 2048)
114: ExpandBuff(true);
115: else
116: available = tokenBegin;
117: }
118:
119: int i;
120: try {
121: if ((i = inputStream.read(buffer, maxNextCharInd, available
122: - maxNextCharInd)) == -1) {
123: inputStream.close();
124: throw new java.io.IOException();
125: } else
126: maxNextCharInd += i;
127: return;
128: } catch (java.io.IOException e) {
129: --bufpos;
130: backup(0);
131: if (tokenBegin == -1)
132: tokenBegin = bufpos;
133: throw e;
134: }
135: }
136:
137: public final char BeginToken() throws java.io.IOException {
138: tokenBegin = -1;
139: char c = readChar();
140: tokenBegin = bufpos;
141:
142: return c;
143: }
144:
145: private final void UpdateLineColumn(char c) {
146: column++;
147:
148: if (prevCharIsLF) {
149: prevCharIsLF = false;
150: line += (column = 1);
151: } else if (prevCharIsCR) {
152: prevCharIsCR = false;
153: if (c == '\n') {
154: prevCharIsLF = true;
155: } else
156: line += (column = 1);
157: }
158:
159: switch (c) {
160: case '\r':
161: prevCharIsCR = true;
162: break;
163: case '\n':
164: prevCharIsLF = true;
165: break;
166: case '\t':
167: column--;
168: column += (8 - (column & 07));
169: break;
170: default:
171: break;
172: }
173:
174: bufline[bufpos] = line;
175: bufcolumn[bufpos] = column;
176: }
177:
178: public final char readChar() throws java.io.IOException {
179: if (inBuf > 0) {
180: --inBuf;
181:
182: if (++bufpos == bufsize)
183: bufpos = 0;
184:
185: return buffer[bufpos];
186: }
187:
188: if (++bufpos >= maxNextCharInd)
189: FillBuff();
190:
191: char c = buffer[bufpos];
192:
193: UpdateLineColumn(c);
194: return (c);
195: }
196:
197: /**
198: * @deprecated
199: * @see #getEndColumn
200: */
201:
202: public final int getColumn() {
203: return bufcolumn[bufpos];
204: }
205:
206: /**
207: * @deprecated
208: * @see #getEndLine
209: */
210:
211: public final int getLine() {
212: return bufline[bufpos];
213: }
214:
215: public final int getEndColumn() {
216: return bufcolumn[bufpos];
217: }
218:
219: public final int getEndLine() {
220: return bufline[bufpos];
221: }
222:
223: public final int getBeginColumn() {
224: return bufcolumn[tokenBegin];
225: }
226:
227: public final int getBeginLine() {
228: return bufline[tokenBegin];
229: }
230:
231: public final void backup(int amount) {
232:
233: inBuf += amount;
234: if ((bufpos -= amount) < 0)
235: bufpos += bufsize;
236: }
237:
238: public SimpleCharStream(java.io.Reader dstream, int startline,
239: int startcolumn, int buffersize) {
240: inputStream = dstream;
241: line = startline;
242: column = startcolumn - 1;
243:
244: available = bufsize = buffersize;
245: buffer = new char[buffersize];
246: bufline = new int[buffersize];
247: bufcolumn = new int[buffersize];
248: }
249:
250: public SimpleCharStream(java.io.Reader dstream, int startline,
251: int startcolumn) {
252: this (dstream, startline, startcolumn, 4096);
253: }
254:
255: public SimpleCharStream(java.io.Reader dstream) {
256: this (dstream, 1, 1, 4096);
257: }
258:
259: public void ReInit(java.io.Reader dstream, int startline,
260: int startcolumn, int buffersize) {
261: inputStream = dstream;
262: line = startline;
263: column = startcolumn - 1;
264:
265: if (buffer == null || buffersize != buffer.length) {
266: available = bufsize = buffersize;
267: buffer = new char[buffersize];
268: bufline = new int[buffersize];
269: bufcolumn = new int[buffersize];
270: }
271: prevCharIsLF = prevCharIsCR = false;
272: tokenBegin = inBuf = maxNextCharInd = 0;
273: bufpos = -1;
274: }
275:
276: public void ReInit(java.io.Reader dstream, int startline,
277: int startcolumn) {
278: ReInit(dstream, startline, startcolumn, 4096);
279: }
280:
281: public void ReInit(java.io.Reader dstream) {
282: ReInit(dstream, 1, 1, 4096);
283: }
284:
285: public SimpleCharStream(java.io.InputStream dstream, int startline,
286: int startcolumn, int buffersize) {
287: this (new java.io.InputStreamReader(dstream), startline,
288: startcolumn, 4096);
289: }
290:
291: public SimpleCharStream(java.io.InputStream dstream, int startline,
292: int startcolumn) {
293: this (dstream, startline, startcolumn, 4096);
294: }
295:
296: public SimpleCharStream(java.io.InputStream dstream) {
297: this (dstream, 1, 1, 4096);
298: }
299:
300: public void ReInit(java.io.InputStream dstream, int startline,
301: int startcolumn, int buffersize) {
302: ReInit(new java.io.InputStreamReader(dstream), startline,
303: startcolumn, 4096);
304: }
305:
306: public void ReInit(java.io.InputStream dstream) {
307: ReInit(dstream, 1, 1, 4096);
308: }
309:
310: public void ReInit(java.io.InputStream dstream, int startline,
311: int startcolumn) {
312: ReInit(dstream, startline, startcolumn, 4096);
313: }
314:
315: public final String GetImage() {
316: if (bufpos >= tokenBegin)
317: return new String(buffer, tokenBegin, bufpos - tokenBegin
318: + 1);
319: else
320: return new String(buffer, tokenBegin, bufsize - tokenBegin)
321: + new String(buffer, 0, bufpos + 1);
322: }
323:
324: public final char[] GetSuffix(int len) {
325: char[] ret = new char[len];
326:
327: if ((bufpos + 1) >= len)
328: System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
329: else {
330: System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret,
331: 0, len - bufpos - 1);
332: System.arraycopy(buffer, 0, ret, len - bufpos - 1,
333: bufpos + 1);
334: }
335:
336: return ret;
337: }
338:
339: public void Done() {
340: buffer = null;
341: bufline = null;
342: bufcolumn = null;
343: }
344:
345: /**
346: * Method to adjust line and column numbers for the start of a token.<BR>
347: */
348: public void adjustBeginLineColumn(int newLine, int newCol) {
349: int start = tokenBegin;
350: int len;
351:
352: if (bufpos >= tokenBegin) {
353: len = bufpos - tokenBegin + inBuf + 1;
354: } else {
355: len = bufsize - tokenBegin + bufpos + 1 + inBuf;
356: }
357:
358: int i = 0, j = 0, k = 0;
359: int nextColDiff = 0, columnDiff = 0;
360:
361: while (i < len
362: && bufline[j = start % bufsize] == bufline[k = ++start
363: % bufsize]) {
364: bufline[j] = newLine;
365: nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
366: bufcolumn[j] = newCol + columnDiff;
367: columnDiff = nextColDiff;
368: i++;
369: }
370:
371: if (i < len) {
372: bufline[j] = newLine++;
373: bufcolumn[j] = newCol + columnDiff;
374:
375: while (i++ < len) {
376: if (bufline[j = start % bufsize] != bufline[++start
377: % bufsize])
378: bufline[j] = newLine++;
379: else
380: bufline[j] = newLine;
381: }
382: }
383:
384: line = bufline[j];
385: column = bufcolumn[j];
386: }
387:
388: }
389:
390: /* END JavaCC SimpleCharStream */
391:
392: /**
393: * Takes and element and an attribute and makes a CharStream that can
394: * be used to parse that attribute's value.
395: */
396:
397: public class AttributeStream extends SimpleCharStream {
398:
399: public AttributeStream(Element elt, String attr) {
400: this (elt, attr, elt.getAttributeValue(attr));
401: }
402:
403: public AttributeStream(Element elt, String attr, String value) {
404: super (new StringReader(value),
405: // TODO: [2003-04-24 ptw] Get attribute location within
406: // element
407: Parser.getSourceLocation(elt, Parser.LINENO, true)
408: .intValue(), Parser.getSourceLocation(elt,
409: Parser.COLNO, true).intValue());
410: }
411: }
|