001    /**
002     * =========================================
003     * LibFormula : a free Java formula library
004     * =========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/libformula/
007     *
008     * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     *
026     * ------------
027     * $Id: JavaCharStream.java 3521 2007-10-16 10:55:14Z tmorgner $
028     * ------------
029     * (C) Copyright 2006-2007, by Pentaho Corporation.
030     */
031    
032    /* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 3.0 */
033    package org.jfree.formula.parser;
034    
035    /**
036     * An implementation of interface CharStream, where the stream is assumed to
037     * contain only ASCII characters (with java-like unicode escape processing).
038     */
039    
040    public class JavaCharStream
041    {
042      public static final boolean staticFlag = false;
043      static int hexval(final char c) throws java.io.IOException {
044        switch(c)
045        {
046           case '0' :
047              return 0;
048           case '1' :
049              return 1;
050           case '2' :
051              return 2;
052           case '3' :
053              return 3;
054           case '4' :
055              return 4;
056           case '5' :
057              return 5;
058           case '6' :
059              return 6;
060           case '7' :
061              return 7;
062           case '8' :
063              return 8;
064           case '9' :
065              return 9;
066    
067           case 'a' :
068           case 'A' :
069              return 10;
070           case 'b' :
071           case 'B' :
072              return 11;
073           case 'c' :
074           case 'C' :
075              return 12;
076           case 'd' :
077           case 'D' :
078              return 13;
079           case 'e' :
080           case 'E' :
081              return 14;
082           case 'f' :
083           case 'F' :
084              return 15;
085        }
086    
087        throw new java.io.IOException(); // Should never come here
088      }
089    
090      public int bufpos = -1;
091      int bufsize;
092      int available;
093      int tokenBegin;
094      protected int[] bufline;
095      protected int[] bufcolumn;
096    
097      protected int column = 0;
098      protected int line = 1;
099    
100      protected boolean prevCharIsCR = false;
101      protected boolean prevCharIsLF = false;
102    
103      protected java.io.Reader inputStream;
104    
105      protected char[] nextCharBuf;
106      protected char[] buffer;
107      protected int maxNextCharInd = 0;
108      protected int nextCharInd = -1;
109      protected int inBuf = 0;
110    
111      protected void ExpandBuff(final boolean wrapAround)
112      {
113         final char[] newbuffer = new char[bufsize + 2048];
114         final int[] newbufline = new int[bufsize + 2048];
115         final int[] newbufcolumn = new int[bufsize + 2048];
116    
117         try
118         {
119            if (wrapAround)
120            {
121               System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
122               System.arraycopy(buffer, 0, newbuffer,
123                                                 bufsize - tokenBegin, bufpos);
124               buffer = newbuffer;
125    
126               System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
127               System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
128               bufline = newbufline;
129    
130               System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
131               System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
132               bufcolumn = newbufcolumn;
133    
134               bufpos += (bufsize - tokenBegin);
135            }
136            else
137            {
138               System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
139               buffer = newbuffer;
140    
141               System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
142               bufline = newbufline;
143    
144               System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
145               bufcolumn = newbufcolumn;
146    
147               bufpos -= tokenBegin;
148            }
149         }
150         catch (Throwable t)
151         {
152            throw new Error(t.getMessage());
153         }
154    
155         available = (bufsize += 2048);
156         tokenBegin = 0;
157      }
158    
159      protected void FillBuff() throws java.io.IOException
160      {
161        if (maxNextCharInd == 4096)
162         {
163           maxNextCharInd = nextCharInd = 0;
164         }
165    
166        try {
167          final int i;
168          if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
169              4096 - maxNextCharInd)) == -1)
170          {
171            inputStream.close();
172            throw new java.io.IOException();
173          }
174              maxNextCharInd += i;
175            return;
176         }
177         catch(java.io.IOException e) {
178            if (bufpos != 0)
179            {
180               --bufpos;
181               backup(0);
182            }
183            else
184            {
185               bufline[bufpos] = line;
186               bufcolumn[bufpos] = column;
187            }
188            throw e;
189         }
190      }
191    
192      protected char ReadByte() throws java.io.IOException
193      {
194         if (++nextCharInd >= maxNextCharInd)
195         {
196           FillBuff();
197         }
198    
199        return nextCharBuf[nextCharInd];
200      }
201    
202      public char BeginToken() throws java.io.IOException
203      {
204         if (inBuf > 0)
205         {
206            --inBuf;
207    
208            if (++bufpos == bufsize)
209            {
210              bufpos = 0;
211            }
212    
213           tokenBegin = bufpos;
214            return buffer[bufpos];
215         }
216    
217         tokenBegin = 0;
218         bufpos = -1;
219    
220         return readChar();
221      }
222    
223      protected void AdjustBuffSize()
224      {
225         if (available == bufsize)
226         {
227            if (tokenBegin > 2048)
228            {
229               bufpos = 0;
230               available = tokenBegin;
231            }
232            else
233            {
234              ExpandBuff(false);
235            }
236         }
237         else if (available > tokenBegin)
238         {
239           available = bufsize;
240         }
241         else if ((tokenBegin - available) < 2048)
242         {
243           ExpandBuff(true);
244         }
245         else
246         {
247           available = tokenBegin;
248         }
249      }
250    
251      protected void UpdateLineColumn(final char c)
252      {
253         column++;
254    
255         if (prevCharIsLF)
256         {
257            prevCharIsLF = false;
258            line += (column = 1);
259         }
260         else if (prevCharIsCR)
261         {
262            prevCharIsCR = false;
263            if (c == '\n')
264            {
265               prevCharIsLF = true;
266            }
267            else
268            {
269              line += (column = 1);
270            }
271         }
272    
273         switch (c)
274         {
275            case '\r' :
276               prevCharIsCR = true;
277               break;
278            case '\n' :
279               prevCharIsLF = true;
280               break;
281            case '\t' :
282               column--;
283               column += (8 - (column & 07));
284               break;
285            default :
286               break;
287         }
288    
289         bufline[bufpos] = line;
290         bufcolumn[bufpos] = column;
291      }
292    
293      public char readChar() throws java.io.IOException
294      {
295         if (inBuf > 0)
296         {
297            --inBuf;
298    
299            if (++bufpos == bufsize)
300            {
301              bufpos = 0;
302            }
303    
304           return buffer[bufpos];
305         }
306    
307        if (++bufpos == available)
308         {
309           AdjustBuffSize();
310         }
311    
312        char c;
313        if ((buffer[bufpos] = c = ReadByte()) == '\\')
314         {
315            UpdateLineColumn(c);
316    
317            int backSlashCnt = 1;
318    
319            for (;;) // Read all the backslashes
320            {
321               if (++bufpos == available)
322               {
323                 AdjustBuffSize();
324               }
325    
326              try
327               {
328                  if ((buffer[bufpos] = c = ReadByte()) != '\\')
329                  {
330                     UpdateLineColumn(c);
331                     // found a non-backslash char.
332                     if ((c == 'u') && ((backSlashCnt & 1) == 1))
333                     {
334                        if (--bufpos < 0)
335                        {
336                          bufpos = bufsize - 1;
337                        }
338    
339                       break;
340                     }
341    
342                     backup(backSlashCnt);
343                     return '\\';
344                  }
345               }
346               catch(java.io.IOException e)
347               {
348                  if (backSlashCnt > 1)
349                  {
350                    backup(backSlashCnt);
351                  }
352    
353                 return '\\';
354               }
355    
356               UpdateLineColumn(c);
357               backSlashCnt++;
358            }
359    
360            // Here, we have seen an odd number of backslash's followed by a 'u'
361            try
362            {
363               while ((c = ReadByte()) == 'u')
364               {
365                 ++column;
366               }
367    
368              buffer[bufpos] = c = (char)(hexval(c) << 12 |
369                                           hexval(ReadByte()) << 8 |
370                                           hexval(ReadByte()) << 4 |
371                                           hexval(ReadByte()));
372    
373               column += 4;
374            }
375            catch(java.io.IOException e)
376            {
377               throw new Error("Invalid escape character at line " + line +
378                                             " column " + column + ".");
379            }
380    
381            if (backSlashCnt == 1)
382            {
383              return c;
384            }
385            else
386            {
387               backup(backSlashCnt - 1);
388               return '\\';
389            }
390         }
391         else
392         {
393            UpdateLineColumn(c);
394            return (c);
395         }
396      }
397    
398      /**
399       * @deprecated
400       * @see #getEndColumn
401       */
402    
403      public int getColumn() {
404         return bufcolumn[bufpos];
405      }
406    
407      /**
408       * @deprecated
409       * @see #getEndLine
410       */
411    
412      public int getLine() {
413         return bufline[bufpos];
414      }
415    
416      public int getEndColumn() {
417         return bufcolumn[bufpos];
418      }
419    
420      public int getEndLine() {
421         return bufline[bufpos];
422      }
423    
424      public int getBeginColumn() {
425         return bufcolumn[tokenBegin];
426      }
427    
428      public int getBeginLine() {
429         return bufline[tokenBegin];
430      }
431    
432      public void backup(final int amount) {
433    
434        inBuf += amount;
435        if ((bufpos -= amount) < 0)
436        {
437          bufpos += bufsize;
438        }
439      }
440    
441      public JavaCharStream(final java.io.Reader dstream,
442                     final int startline, final int startcolumn, final int buffersize)
443      {
444        inputStream = dstream;
445        line = startline;
446        column = startcolumn - 1;
447    
448        available = bufsize = buffersize;
449        buffer = new char[buffersize];
450        bufline = new int[buffersize];
451        bufcolumn = new int[buffersize];
452        nextCharBuf = new char[4096];
453      }
454    
455      public JavaCharStream(final java.io.Reader dstream,
456                                            final int startline, final int startcolumn)
457      {
458         this(dstream, startline, startcolumn, 4096);
459      }
460    
461      public JavaCharStream(final java.io.Reader dstream)
462      {
463         this(dstream, 1, 1, 4096);
464      }
465      public void ReInit(final java.io.Reader dstream,
466                     final int startline, final int startcolumn, final int buffersize)
467      {
468        inputStream = dstream;
469        line = startline;
470        column = startcolumn - 1;
471    
472        if (buffer == null || buffersize != buffer.length)
473        {
474          available = bufsize = buffersize;
475          buffer = new char[buffersize];
476          bufline = new int[buffersize];
477          bufcolumn = new int[buffersize];
478          nextCharBuf = new char[4096];
479        }
480        prevCharIsLF = prevCharIsCR = false;
481        tokenBegin = inBuf = maxNextCharInd = 0;
482        nextCharInd = bufpos = -1;
483      }
484    
485      public void ReInit(final java.io.Reader dstream,
486                                            final int startline, final int startcolumn)
487      {
488         ReInit(dstream, startline, startcolumn, 4096);
489      }
490    
491      public void ReInit(final java.io.Reader dstream)
492      {
493         ReInit(dstream, 1, 1, 4096);
494      }
495      public JavaCharStream(final java.io.InputStream dstream, final int startline,
496      final int startcolumn, final int buffersize)
497      {
498         this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
499      }
500    
501      public JavaCharStream(final java.io.InputStream dstream, final int startline,
502                                                               final int startcolumn)
503      {
504         this(dstream, startline, startcolumn, 4096);
505      }
506    
507      public JavaCharStream(final java.io.InputStream dstream)
508      {
509         this(dstream, 1, 1, 4096);
510      }
511    
512      public void ReInit(final java.io.InputStream dstream, final int startline,
513      final int startcolumn, final int buffersize)
514      {
515         ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
516      }
517      public void ReInit(final java.io.InputStream dstream, final int startline,
518                                                               final int startcolumn)
519      {
520         ReInit(dstream, startline, startcolumn, 4096);
521      }
522      public void ReInit(final java.io.InputStream dstream)
523      {
524         ReInit(dstream, 1, 1, 4096);
525      }
526    
527      public String GetImage()
528      {
529         if (bufpos >= tokenBegin)
530         {
531           return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
532         }
533         else
534         {
535           return new String(buffer, tokenBegin, bufsize - tokenBegin) +
536               new String(buffer, 0, bufpos + 1);
537         }
538      }
539    
540      public char[] GetSuffix(final int len)
541      {
542         final char[] ret = new char[len];
543    
544         if ((bufpos + 1) >= len)
545         {
546           System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
547         }
548         else
549         {
550            System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
551                                                              len - bufpos - 1);
552            System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
553         }
554    
555         return ret;
556      }
557    
558      public void Done()
559      {
560         nextCharBuf = null;
561         buffer = null;
562         bufline = null;
563         bufcolumn = null;
564      }
565    
566      /**
567       * Method to adjust line and column numbers for the start of a token.
568       */
569      public void adjustBeginLineColumn(int newLine, final int newCol)
570      {
571         int start = tokenBegin;
572         final int len;
573    
574         if (bufpos >= tokenBegin)
575         {
576            len = bufpos - tokenBegin + inBuf + 1;
577         }
578         else
579         {
580            len = bufsize - tokenBegin + bufpos + 1 + inBuf;
581         }
582    
583         int i = 0;
584        int j = 0;
585        int k;
586        int nextColDiff;
587        int columnDiff = 0;
588    
589        while (i < len &&
590                bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
591         {
592            bufline[j] = newLine;
593            nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
594            bufcolumn[j] = newCol + columnDiff;
595            columnDiff = nextColDiff;
596            i++;
597         }
598    
599         if (i < len)
600         {
601            bufline[j] = newLine++;
602            bufcolumn[j] = newCol + columnDiff;
603    
604            while (i++ < len)
605            {
606               if (bufline[j = start % bufsize] != bufline[++start % bufsize])
607               {
608                 bufline[j] = newLine++;
609               }
610               else
611               {
612                 bufline[j] = newLine;
613               }
614            }
615         }
616    
617         line = bufline[j];
618         column = bufcolumn[j];
619      }
620    
621    }