c5533b78fb474117ab69cf5dc3564707277522cb
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Scanner.java
1 /***********************************************************************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. All rights reserved. This program and the
3  * accompanying materials are made available under the terms of the Common Public License v0.5 which accompanies this distribution,
4  * and is available at http://www.eclipse.org/legal/cpl-v05.html
5  * 
6  * Contributors: IBM Corporation - initial API and implementation
7  **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.parser;
9
10 import java.util.ArrayList;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Stack;
14
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.IScanner;
17 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
18 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
19 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
21
22 public class Scanner implements IScanner, ITerminalSymbols {
23   /*
24    * APIs ares - getNextToken() which return the current type of the token (this value is not memorized by the scanner) -
25    * getCurrentTokenSource() which provides with the token "REAL" source (aka all unicode have been transformed into a correct char) -
26    * sourceStart gives the position into the stream - currentPosition-1 gives the sourceEnd position into the stream
27    */
28   // 1.4 feature
29   private boolean assertMode;
30
31   public boolean useAssertAsAnIndentifier = false;
32
33   //flag indicating if processed source contains occurrences of keyword assert
34   public boolean containsAssertKeyword = false;
35
36   public boolean recordLineSeparator;
37
38   public boolean ignorePHPOneLiner = false;
39
40   public boolean phpMode = false;
41
42   public Stack encapsedStringStack = null;
43
44   public char currentCharacter;
45
46   public int startPosition;
47
48   public int currentPosition;
49
50   public int initialPosition, eofPosition;
51
52   // after this position eof are generated instead of real token from the
53   // source
54   public boolean tokenizeComments;
55
56   public boolean tokenizeWhiteSpace;
57
58   public boolean tokenizeStrings;
59
60   //source should be viewed as a window (aka a part)
61   //of a entire very large stream
62   public char source[];
63
64   //unicode support
65   public char[] withoutUnicodeBuffer;
66
67   public int withoutUnicodePtr;
68
69   //when == 0 ==> no unicode in the current token
70   public boolean unicodeAsBackSlash = false;
71
72   public boolean scanningFloatLiteral = false;
73
74   //support for /** comments
75   public int[] commentStops = new int[10];
76
77   public int[] commentStarts = new int[10];
78
79   public int commentPtr = -1; // no comment test with commentPtr value -1
80
81   protected int lastCommentLinePosition = -1;
82
83   //diet parsing support - jump over some method body when requested
84   public boolean diet = false;
85
86   //support for the poor-line-debuggers ....
87   //remember the position of the cr/lf
88   public int[] lineEnds = new int[250];
89
90   public int linePtr = -1;
91
92   public boolean wasAcr = false;
93
94   public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
95
96   public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
97
98   public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
99
100   public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$
101
102   public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
103
104   public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
105
106   public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
107
108   public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
109
110   public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
111
112   public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
113
114   public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
115
116   public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
117
118   //----------------optimized identifier managment------------------
119   static final char[] charArray_a = new char[] { 'a' }, charArray_b = new char[] { 'b' }, charArray_c = new char[] { 'c' },
120       charArray_d = new char[] { 'd' }, charArray_e = new char[] { 'e' }, charArray_f = new char[] { 'f' },
121       charArray_g = new char[] { 'g' }, charArray_h = new char[] { 'h' }, charArray_i = new char[] { 'i' },
122       charArray_j = new char[] { 'j' }, charArray_k = new char[] { 'k' }, charArray_l = new char[] { 'l' },
123       charArray_m = new char[] { 'm' }, charArray_n = new char[] { 'n' }, charArray_o = new char[] { 'o' },
124       charArray_p = new char[] { 'p' }, charArray_q = new char[] { 'q' }, charArray_r = new char[] { 'r' },
125       charArray_s = new char[] { 's' }, charArray_t = new char[] { 't' }, charArray_u = new char[] { 'u' },
126       charArray_v = new char[] { 'v' }, charArray_w = new char[] { 'w' }, charArray_x = new char[] { 'x' },
127       charArray_y = new char[] { 'y' }, charArray_z = new char[] { 'z' };
128
129   static final char[] charArray_va = new char[] { '$', 'a' }, charArray_vb = new char[] { '$', 'b' }, charArray_vc = new char[] {
130       '$',
131       'c' }, charArray_vd = new char[] { '$', 'd' }, charArray_ve = new char[] { '$', 'e' },
132       charArray_vf = new char[] { '$', 'f' }, charArray_vg = new char[] { '$', 'g' }, charArray_vh = new char[] { '$', 'h' },
133       charArray_vi = new char[] { '$', 'i' }, charArray_vj = new char[] { '$', 'j' }, charArray_vk = new char[] { '$', 'k' },
134       charArray_vl = new char[] { '$', 'l' }, charArray_vm = new char[] { '$', 'm' }, charArray_vn = new char[] { '$', 'n' },
135       charArray_vo = new char[] { '$', 'o' }, charArray_vp = new char[] { '$', 'p' }, charArray_vq = new char[] { '$', 'q' },
136       charArray_vr = new char[] { '$', 'r' }, charArray_vs = new char[] { '$', 's' }, charArray_vt = new char[] { '$', 't' },
137       charArray_vu = new char[] { '$', 'u' }, charArray_vv = new char[] { '$', 'v' }, charArray_vw = new char[] { '$', 'w' },
138       charArray_vx = new char[] { '$', 'x' }, charArray_vy = new char[] { '$', 'y' }, charArray_vz = new char[] { '$', 'z' };
139
140   static final char[] initCharArray = new char[] { '\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000' };
141
142   static final int TableSize = 30, InternalTableSize = 6;
143
144   //30*6 = 180 entries
145   public static final int OptimizedLength = 6;
146
147   public/* static */
148   final char[][][][] charArray_length = new char[OptimizedLength][TableSize][InternalTableSize][];
149
150   // support for detecting non-externalized string literals
151   int currentLineNr = -1;
152
153   int previousLineNr = -1;
154
155   NLSLine currentLine = null;
156
157   List lines = new ArrayList();
158
159   public static final String TAG_PREFIX = "//$NON-NLS-"; //$NON-NLS-1$
160
161   public static final int TAG_PREFIX_LENGTH = TAG_PREFIX.length();
162
163   public static final String TAG_POSTFIX = "$"; //$NON-NLS-1$
164
165   public static final int TAG_POSTFIX_LENGTH = TAG_POSTFIX.length();
166
167   public StringLiteral[] nonNLSStrings = null;
168
169   public boolean checkNonExternalizedStringLiterals = true;
170
171   public boolean wasNonExternalizedStringLiteral = false;
172   /* static */{
173     for (int i = 0; i < 6; i++) {
174       for (int j = 0; j < TableSize; j++) {
175         for (int k = 0; k < InternalTableSize; k++) {
176           charArray_length[i][j][k] = initCharArray;
177         }
178       }
179     }
180   }
181
182   static int newEntry2 = 0, newEntry3 = 0, newEntry4 = 0, newEntry5 = 0, newEntry6 = 0;
183
184   public static final int RoundBracket = 0;
185
186   public static final int SquareBracket = 1;
187
188   public static final int CurlyBracket = 2;
189
190   public static final int BracketKinds = 3;
191
192   // task tag support
193   public char[][] foundTaskTags = null;
194
195   public char[][] foundTaskMessages;
196
197   public char[][] foundTaskPriorities = null;
198
199   public int[][] foundTaskPositions;
200
201   public int foundTaskCount = 0;
202
203   public char[][] taskTags = null;
204
205   public char[][] taskPriorities = null;
206
207   public boolean isTaskCaseSensitive = true;
208
209   public static final boolean DEBUG = false;
210
211   public static final boolean TRACE = false;
212
213   public ICompilationUnit compilationUnit = null;
214
215   /**
216    * Determines if the specified character is permissible as the first character in a PHP identifier or variable
217    * 
218    * The '$' character for PHP variables is regarded as a correct first character !
219    *  
220    */
221   public static boolean isPHPIdentOrVarStart(char ch) {
222     return Character.isLetter(ch) || (ch == '$') || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
223   }
224
225   /**
226    * Determines if the specified character is permissible as the first character in a PHP identifier.
227    * 
228    * The '$' character for PHP variables isn't regarded as the first character !
229    */
230   public static boolean isPHPIdentifierStart(char ch) {
231     return Character.isLetter(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
232   }
233
234   /**
235    * Determines if the specified character may be part of a PHP identifier as other than the first character
236    */
237   public static boolean isPHPIdentifierPart(char ch) {
238     return Character.isLetterOrDigit(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
239   }
240
241   public final boolean atEnd() {
242     // This code is not relevant if source is
243     // Only a part of the real stream input
244     return source.length == currentPosition;
245   }
246
247   public char[] getCurrentIdentifierSource() {
248     //return the token REAL source (aka unicodes are precomputed)
249     char[] result;
250     //    if (withoutUnicodePtr != 0)
251     //      //0 is used as a fast test flag so the real first char is in position 1
252     //      System.arraycopy(
253     //        withoutUnicodeBuffer,
254     //        1,
255     //        result = new char[withoutUnicodePtr],
256     //        0,
257     //        withoutUnicodePtr);
258     //    else {
259     int length = currentPosition - startPosition;
260     switch (length) { // see OptimizedLength
261     case 1:
262       return optimizedCurrentTokenSource1();
263     case 2:
264       return optimizedCurrentTokenSource2();
265     case 3:
266       return optimizedCurrentTokenSource3();
267     case 4:
268       return optimizedCurrentTokenSource4();
269     case 5:
270       return optimizedCurrentTokenSource5();
271     case 6:
272       return optimizedCurrentTokenSource6();
273     }
274     //no optimization
275     System.arraycopy(source, startPosition, result = new char[length], 0, length);
276     //   }
277     return result;
278   }
279
280   public int getCurrentTokenEndPosition() {
281     return this.currentPosition - 1;
282   }
283
284   public final char[] getCurrentTokenSource() {
285     // Return the token REAL source (aka unicodes are precomputed)
286     char[] result;
287     //    if (withoutUnicodePtr != 0)
288     //      // 0 is used as a fast test flag so the real first char is in position 1
289     //      System.arraycopy(
290     //        withoutUnicodeBuffer,
291     //        1,
292     //        result = new char[withoutUnicodePtr],
293     //        0,
294     //        withoutUnicodePtr);
295     //    else {
296     int length;
297     System.arraycopy(source, startPosition, result = new char[length = currentPosition - startPosition], 0, length);
298     //    }
299     return result;
300   }
301
302   public final char[] getCurrentTokenSource(int startPos) {
303     // Return the token REAL source (aka unicodes are precomputed)
304     char[] result;
305     //    if (withoutUnicodePtr != 0)
306     //      // 0 is used as a fast test flag so the real first char is in position 1
307     //      System.arraycopy(
308     //        withoutUnicodeBuffer,
309     //        1,
310     //        result = new char[withoutUnicodePtr],
311     //        0,
312     //        withoutUnicodePtr);
313     //    else {
314     int length;
315     System.arraycopy(source, startPos, result = new char[length = currentPosition - startPos], 0, length);
316     //  }
317     return result;
318   }
319
320   public final char[] getCurrentTokenSourceString() {
321     //return the token REAL source (aka unicodes are precomputed).
322     //REMOVE the two " that are at the beginning and the end.
323     char[] result;
324     if (withoutUnicodePtr != 0)
325       //0 is used as a fast test flag so the real first char is in position 1
326       System.arraycopy(withoutUnicodeBuffer, 2,
327       //2 is 1 (real start) + 1 (to jump over the ")
328           result = new char[withoutUnicodePtr - 2], 0, withoutUnicodePtr - 2);
329     else {
330       int length;
331       System.arraycopy(source, startPosition + 1, result = new char[length = currentPosition - startPosition - 2], 0, length);
332     }
333     return result;
334   }
335
336   public final char[] getRawTokenSourceEnd() {
337     int length = this.eofPosition - this.currentPosition - 1;
338     char[] sourceEnd = new char[length];
339     System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length);
340     return sourceEnd;
341   }
342
343   public int getCurrentTokenStartPosition() {
344     return this.startPosition;
345   }
346
347   public final char[] getCurrentStringLiteralSource() {
348     // Return the token REAL source (aka unicodes are precomputed)
349     if (startPosition + 1 >= currentPosition) {
350       return new char[0];
351     }
352     char[] result;
353     int length;
354     System.arraycopy(source, startPosition + 1, result = new char[length = currentPosition - startPosition - 2], 0, length);
355     //    }
356     return result;
357   }
358
359   public final char[] getCurrentStringLiteralSource(int startPos) {
360     // Return the token REAL source (aka unicodes are precomputed)
361     char[] result;
362     int length;
363     System.arraycopy(source, startPos + 1, result = new char[length = currentPosition - startPos - 2], 0, length);
364     //    }
365     return result;
366   }
367
368   /*
369    * Search the source position corresponding to the end of a given line number
370    * 
371    * Line numbers are 1-based, and relative to the scanner initialPosition. Character positions are 0-based.
372    * 
373    * In case the given line number is inconsistent, answers -1.
374    */
375   public final int getLineEnd(int lineNumber) {
376     if (lineEnds == null)
377       return -1;
378     if (lineNumber >= lineEnds.length)
379       return -1;
380     if (lineNumber <= 0)
381       return -1;
382     if (lineNumber == lineEnds.length - 1)
383       return eofPosition;
384     return lineEnds[lineNumber - 1];
385     // next line start one character behind the lineEnd of the previous line
386   }
387
388   /**
389    * Search the source position corresponding to the beginning of a given line number
390    * 
391    * Line numbers are 1-based, and relative to the scanner initialPosition. Character positions are 0-based.
392    * 
393    * e.g. getLineStart(1) --> 0 i.e. first line starts at character 0.
394    * 
395    * In case the given line number is inconsistent, answers -1.
396    */
397   public final int getLineStart(int lineNumber) {
398     if (lineEnds == null)
399       return -1;
400     if (lineNumber >= lineEnds.length)
401       return -1;
402     if (lineNumber <= 0)
403       return -1;
404     if (lineNumber == 1)
405       return initialPosition;
406     return lineEnds[lineNumber - 2] + 1;
407     // next line start one character behind the lineEnd of the previous line
408   }
409
410   public final boolean getNextChar(char testedChar) {
411     //BOOLEAN
412     //handle the case of unicode.
413     //when a unicode appears then we must use a buffer that holds char
414     // internal values
415     //At the end of this method currentCharacter holds the new visited char
416     //and currentPosition points right next after it
417     //Both previous lines are true if the currentCharacter is == to the
418     // testedChar
419     //On false, no side effect has occured.
420     //ALL getNextChar.... ARE OPTIMIZED COPIES
421     int temp = currentPosition;
422     try {
423       currentCharacter = source[currentPosition++];
424       //      if (((currentCharacter = source[currentPosition++]) == '\\')
425       //        && (source[currentPosition] == 'u')) {
426       //        //-------------unicode traitement ------------
427       //        int c1, c2, c3, c4;
428       //        int unicodeSize = 6;
429       //        currentPosition++;
430       //        while (source[currentPosition] == 'u') {
431       //          currentPosition++;
432       //          unicodeSize++;
433       //        }
434       //
435       //        if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
436       //          || c1 < 0)
437       //          || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
438       //            || c2 < 0)
439       //          || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
440       //            || c3 < 0)
441       //          || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
442       //            || c4 < 0)) {
443       //          currentPosition = temp;
444       //          return false;
445       //        }
446       //
447       //        currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
448       //        if (currentCharacter != testedChar) {
449       //          currentPosition = temp;
450       //          return false;
451       //        }
452       //        unicodeAsBackSlash = currentCharacter == '\\';
453       //
454       //        //need the unicode buffer
455       //        if (withoutUnicodePtr == 0) {
456       //          //buffer all the entries that have been left aside....
457       //          withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
458       //          System.arraycopy(
459       //            source,
460       //            startPosition,
461       //            withoutUnicodeBuffer,
462       //            1,
463       //            withoutUnicodePtr);
464       //        }
465       //        //fill the buffer with the char
466       //        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
467       //        return true;
468       //
469       //      } //-------------end unicode traitement--------------
470       //      else {
471       if (currentCharacter != testedChar) {
472         currentPosition = temp;
473         return false;
474       }
475       unicodeAsBackSlash = false;
476       //        if (withoutUnicodePtr != 0)
477       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
478       return true;
479       //      }
480     } catch (IndexOutOfBoundsException e) {
481       unicodeAsBackSlash = false;
482       currentPosition = temp;
483       return false;
484     }
485   }
486
487   public final int getNextChar(char testedChar1, char testedChar2) {
488     //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
489     //test can be done with (x==0) for the first and (x>0) for the second
490     //handle the case of unicode.
491     //when a unicode appears then we must use a buffer that holds char
492     // internal values
493     //At the end of this method currentCharacter holds the new visited char
494     //and currentPosition points right next after it
495     //Both previous lines are true if the currentCharacter is == to the
496     // testedChar1/2
497     //On false, no side effect has occured.
498     //ALL getNextChar.... ARE OPTIMIZED COPIES
499     int temp = currentPosition;
500     try {
501       int result;
502       currentCharacter = source[currentPosition++];
503       //      if (((currentCharacter = source[currentPosition++]) == '\\')
504       //        && (source[currentPosition] == 'u')) {
505       //        //-------------unicode traitement ------------
506       //        int c1, c2, c3, c4;
507       //        int unicodeSize = 6;
508       //        currentPosition++;
509       //        while (source[currentPosition] == 'u') {
510       //          currentPosition++;
511       //          unicodeSize++;
512       //        }
513       //
514       //        if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
515       //          || c1 < 0)
516       //          || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
517       //            || c2 < 0)
518       //          || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
519       //            || c3 < 0)
520       //          || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
521       //            || c4 < 0)) {
522       //          currentPosition = temp;
523       //          return 2;
524       //        }
525       //
526       //        currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
527       //        if (currentCharacter == testedChar1)
528       //          result = 0;
529       //        else if (currentCharacter == testedChar2)
530       //          result = 1;
531       //        else {
532       //          currentPosition = temp;
533       //          return -1;
534       //        }
535       //
536       //        //need the unicode buffer
537       //        if (withoutUnicodePtr == 0) {
538       //          //buffer all the entries that have been left aside....
539       //          withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
540       //          System.arraycopy(
541       //            source,
542       //            startPosition,
543       //            withoutUnicodeBuffer,
544       //            1,
545       //            withoutUnicodePtr);
546       //        }
547       //        //fill the buffer with the char
548       //        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
549       //        return result;
550       //      } //-------------end unicode traitement--------------
551       //      else {
552       if (currentCharacter == testedChar1)
553         result = 0;
554       else if (currentCharacter == testedChar2)
555         result = 1;
556       else {
557         currentPosition = temp;
558         return -1;
559       }
560       //        if (withoutUnicodePtr != 0)
561       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
562       return result;
563       //     }
564     } catch (IndexOutOfBoundsException e) {
565       currentPosition = temp;
566       return -1;
567     }
568   }
569
570   public final boolean getNextCharAsDigit() {
571     //BOOLEAN
572     //handle the case of unicode.
573     //when a unicode appears then we must use a buffer that holds char
574     // internal values
575     //At the end of this method currentCharacter holds the new visited char
576     //and currentPosition points right next after it
577     //Both previous lines are true if the currentCharacter is a digit
578     //On false, no side effect has occured.
579     //ALL getNextChar.... ARE OPTIMIZED COPIES
580     int temp = currentPosition;
581     try {
582       currentCharacter = source[currentPosition++];
583       //      if (((currentCharacter = source[currentPosition++]) == '\\')
584       //        && (source[currentPosition] == 'u')) {
585       //        //-------------unicode traitement ------------
586       //        int c1, c2, c3, c4;
587       //        int unicodeSize = 6;
588       //        currentPosition++;
589       //        while (source[currentPosition] == 'u') {
590       //          currentPosition++;
591       //          unicodeSize++;
592       //        }
593       //
594       //        if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
595       //          || c1 < 0)
596       //          || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
597       //            || c2 < 0)
598       //          || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
599       //            || c3 < 0)
600       //          || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
601       //            || c4 < 0)) {
602       //          currentPosition = temp;
603       //          return false;
604       //        }
605       //
606       //        currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
607       //        if (!Character.isDigit(currentCharacter)) {
608       //          currentPosition = temp;
609       //          return false;
610       //        }
611       //
612       //        //need the unicode buffer
613       //        if (withoutUnicodePtr == 0) {
614       //          //buffer all the entries that have been left aside....
615       //          withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
616       //          System.arraycopy(
617       //            source,
618       //            startPosition,
619       //            withoutUnicodeBuffer,
620       //            1,
621       //            withoutUnicodePtr);
622       //        }
623       //        //fill the buffer with the char
624       //        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
625       //        return true;
626       //      } //-------------end unicode traitement--------------
627       //      else {
628       if (!Character.isDigit(currentCharacter)) {
629         currentPosition = temp;
630         return false;
631       }
632       //        if (withoutUnicodePtr != 0)
633       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
634       return true;
635       //      }
636     } catch (IndexOutOfBoundsException e) {
637       currentPosition = temp;
638       return false;
639     }
640   }
641
642   public final boolean getNextCharAsDigit(int radix) {
643     //BOOLEAN
644     //handle the case of unicode.
645     //when a unicode appears then we must use a buffer that holds char
646     // internal values
647     //At the end of this method currentCharacter holds the new visited char
648     //and currentPosition points right next after it
649     //Both previous lines are true if the currentCharacter is a digit base on
650     // radix
651     //On false, no side effect has occured.
652     //ALL getNextChar.... ARE OPTIMIZED COPIES
653     int temp = currentPosition;
654     try {
655       currentCharacter = source[currentPosition++];
656       //      if (((currentCharacter = source[currentPosition++]) == '\\')
657       //        && (source[currentPosition] == 'u')) {
658       //        //-------------unicode traitement ------------
659       //        int c1, c2, c3, c4;
660       //        int unicodeSize = 6;
661       //        currentPosition++;
662       //        while (source[currentPosition] == 'u') {
663       //          currentPosition++;
664       //          unicodeSize++;
665       //        }
666       //
667       //        if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
668       //          || c1 < 0)
669       //          || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
670       //            || c2 < 0)
671       //          || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
672       //            || c3 < 0)
673       //          || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
674       //            || c4 < 0)) {
675       //          currentPosition = temp;
676       //          return false;
677       //        }
678       //
679       //        currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
680       //        if (Character.digit(currentCharacter, radix) == -1) {
681       //          currentPosition = temp;
682       //          return false;
683       //        }
684       //
685       //        //need the unicode buffer
686       //        if (withoutUnicodePtr == 0) {
687       //          //buffer all the entries that have been left aside....
688       //          withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
689       //          System.arraycopy(
690       //            source,
691       //            startPosition,
692       //            withoutUnicodeBuffer,
693       //            1,
694       //            withoutUnicodePtr);
695       //        }
696       //        //fill the buffer with the char
697       //        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
698       //        return true;
699       //      } //-------------end unicode traitement--------------
700       //      else {
701       if (Character.digit(currentCharacter, radix) == -1) {
702         currentPosition = temp;
703         return false;
704       }
705       //        if (withoutUnicodePtr != 0)
706       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
707       return true;
708       //      }
709     } catch (IndexOutOfBoundsException e) {
710       currentPosition = temp;
711       return false;
712     }
713   }
714
715   public boolean getNextCharAsJavaIdentifierPart() {
716     //BOOLEAN
717     //handle the case of unicode.
718     //when a unicode appears then we must use a buffer that holds char
719     // internal values
720     //At the end of this method currentCharacter holds the new visited char
721     //and currentPosition points right next after it
722     //Both previous lines are true if the currentCharacter is a
723     // JavaIdentifierPart
724     //On false, no side effect has occured.
725     //ALL getNextChar.... ARE OPTIMIZED COPIES
726     int temp = currentPosition;
727     try {
728       currentCharacter = source[currentPosition++];
729       //      if (((currentCharacter = source[currentPosition++]) == '\\')
730       //        && (source[currentPosition] == 'u')) {
731       //        //-------------unicode traitement ------------
732       //        int c1, c2, c3, c4;
733       //        int unicodeSize = 6;
734       //        currentPosition++;
735       //        while (source[currentPosition] == 'u') {
736       //          currentPosition++;
737       //          unicodeSize++;
738       //        }
739       //
740       //        if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
741       //          || c1 < 0)
742       //          || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
743       //            || c2 < 0)
744       //          || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
745       //            || c3 < 0)
746       //          || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
747       //            || c4 < 0)) {
748       //          currentPosition = temp;
749       //          return false;
750       //        }
751       //
752       //        currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
753       //        if (!isPHPIdentifierPart(currentCharacter)) {
754       //          currentPosition = temp;
755       //          return false;
756       //        }
757       //
758       //        //need the unicode buffer
759       //        if (withoutUnicodePtr == 0) {
760       //          //buffer all the entries that have been left aside....
761       //          withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
762       //          System.arraycopy(
763       //            source,
764       //            startPosition,
765       //            withoutUnicodeBuffer,
766       //            1,
767       //            withoutUnicodePtr);
768       //        }
769       //        //fill the buffer with the char
770       //        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
771       //        return true;
772       //      } //-------------end unicode traitement--------------
773       //      else {
774       if (!isPHPIdentifierPart(currentCharacter)) {
775         currentPosition = temp;
776         return false;
777       }
778       //        if (withoutUnicodePtr != 0)
779       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
780       return true;
781       //      }
782     } catch (IndexOutOfBoundsException e) {
783       currentPosition = temp;
784       return false;
785     }
786   }
787
788   public int getCastOrParen() {
789     int tempPosition = currentPosition;
790     char tempCharacter = currentCharacter;
791     int tempToken = TokenNameLPAREN;
792     boolean found = false;
793     StringBuffer buf = new StringBuffer();
794     try {
795       do {
796         currentCharacter = source[currentPosition++];
797       } while (currentCharacter == ' ' || currentCharacter == '\t');
798       while ((currentCharacter >= 'a' && currentCharacter <= 'z') || (currentCharacter >= 'A' && currentCharacter <= 'Z')) {
799         buf.append(currentCharacter);
800         currentCharacter = source[currentPosition++];
801       }
802       if (buf.length() >= 3 && buf.length() <= 7) {
803         char[] data = buf.toString().toCharArray();
804         int index = 0;
805         switch (data.length) {
806         case 3:
807           // int
808           if ((data[index] == 'i') && (data[++index] == 'n') && (data[++index] == 't')) {
809             found = true;
810             tempToken = TokenNameintCAST;
811           }
812           break;
813         case 4:
814           // bool real
815           if ((data[index] == 'b') && (data[++index] == 'o') && (data[++index] == 'o') && (data[++index] == 'l')) {
816             found = true;
817             tempToken = TokenNameboolCAST;
818           } else {
819             index = 0;
820             if ((data[index] == 'r') && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'l')) {
821               found = true;
822               tempToken = TokenNamedoubleCAST;
823             }
824           }
825           break;
826         case 5:
827           // array unset float
828           if ((data[index] == 'a') && (data[++index] == 'r') && (data[++index] == 'r') && (data[++index] == 'a')
829               && (data[++index] == 'y')) {
830             found = true;
831             tempToken = TokenNamearrayCAST;
832           } else {
833             index = 0;
834             if ((data[index] == 'u') && (data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 'e')
835                 && (data[++index] == 't')) {
836               found = true;
837               tempToken = TokenNameunsetCAST;
838             } else {
839               index = 0;
840               if ((data[index] == 'f') && (data[++index] == 'l') && (data[++index] == 'o') && (data[++index] == 'a')
841                   && (data[++index] == 't')) {
842                 found = true;
843                 tempToken = TokenNamedoubleCAST;
844               }
845             }
846           }
847           break;
848         case 6:
849           // object string double
850           if ((data[index] == 'o') && (data[++index] == 'b') && (data[++index] == 'j') && (data[++index] == 'e')
851               && (data[++index] == 'c') && (data[++index] == 't')) {
852             found = true;
853             tempToken = TokenNameobjectCAST;
854           } else {
855             index = 0;
856             if ((data[index] == 's') && (data[++index] == 't') && (data[++index] == 'r') && (data[++index] == 'i')
857                 && (data[++index] == 'n') && (data[++index] == 'g')) {
858               found = true;
859               tempToken = TokenNamestringCAST;
860             } else {
861               index = 0;
862               if ((data[index] == 'd') && (data[++index] == 'o') && (data[++index] == 'u') && (data[++index] == 'b')
863                   && (data[++index] == 'l') && (data[++index] == 'e')) {
864                 found = true;
865                 tempToken = TokenNamedoubleCAST;
866               }
867             }
868           }
869           break;
870         case 7:
871           // boolean integer
872           if ((data[index] == 'b') && (data[++index] == 'o') && (data[++index] == 'o') && (data[++index] == 'l')
873               && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'n')) {
874             found = true;
875             tempToken = TokenNameboolCAST;
876           } else {
877             index = 0;
878             if ((data[index] == 'i') && (data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 'e')
879                 && (data[++index] == 'g') && (data[++index] == 'e') && (data[++index] == 'r')) {
880               found = true;
881               tempToken = TokenNameintCAST;
882             }
883           }
884           break;
885         }
886         if (found) {
887           while (currentCharacter == ' ' || currentCharacter == '\t') {
888             currentCharacter = source[currentPosition++];
889           }
890           if (currentCharacter == ')') {
891             return tempToken;
892           }
893         }
894       }
895     } catch (IndexOutOfBoundsException e) {
896     }
897     currentCharacter = tempCharacter;
898     currentPosition = tempPosition;
899     return TokenNameLPAREN;
900   }
901
902   public void consumeStringInterpolated() throws InvalidInputException {
903     try {
904       // consume next character
905       unicodeAsBackSlash = false;
906       currentCharacter = source[currentPosition++];
907       //                if (((currentCharacter = source[currentPosition++]) == '\\')
908       //                  && (source[currentPosition] == 'u')) {
909       //                  getNextUnicodeChar();
910       //                } else {
911       //                  if (withoutUnicodePtr != 0) {
912       //                    withoutUnicodeBuffer[++withoutUnicodePtr] =
913       //                      currentCharacter;
914       //                  }
915       //                }
916       while (currentCharacter != '`') {
917         /** ** in PHP \r and \n are valid in string literals *** */
918         //                if ((currentCharacter == '\n')
919         //                  || (currentCharacter == '\r')) {
920         //                  // relocate if finding another quote fairly close: thus unicode
921         // '/u000D' will be fully consumed
922         //                  for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
923         //                    if (currentPosition + lookAhead == source.length)
924         //                      break;
925         //                    if (source[currentPosition + lookAhead] == '\n')
926         //                      break;
927         //                    if (source[currentPosition + lookAhead] == '\"') {
928         //                      currentPosition += lookAhead + 1;
929         //                      break;
930         //                    }
931         //                  }
932         //                  throw new InvalidInputException(INVALID_CHAR_IN_STRING);
933         //                }
934         if (currentCharacter == '\\') {
935           int escapeSize = currentPosition;
936           boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
937           //scanEscapeCharacter make a side effect on this value and we need
938           // the previous value few lines down this one
939           scanDoubleQuotedEscapeCharacter();
940           escapeSize = currentPosition - escapeSize;
941           if (withoutUnicodePtr == 0) {
942             //buffer all the entries that have been left aside....
943             withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
944             System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
945             withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
946           } else { //overwrite the / in the buffer
947             withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
948             if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
949               // where only one is correct
950               withoutUnicodePtr--;
951             }
952           }
953         }
954         // consume next character
955         unicodeAsBackSlash = false;
956         currentCharacter = source[currentPosition++];
957         //                  if (((currentCharacter = source[currentPosition++]) == '\\')
958         //                    && (source[currentPosition] == 'u')) {
959         //                    getNextUnicodeChar();
960         //                  } else {
961         if (withoutUnicodePtr != 0) {
962           withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
963         }
964         //                  }
965       }
966     } catch (IndexOutOfBoundsException e) {
967       //    reset end position for error reporting
968       currentPosition -= 2;
969       throw new InvalidInputException(UNTERMINATED_STRING);
970     } catch (InvalidInputException e) {
971       if (e.getMessage().equals(INVALID_ESCAPE)) {
972         // relocate if finding another quote fairly close: thus unicode
973         // '/u000D' will be fully consumed
974         for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
975           if (currentPosition + lookAhead == source.length)
976             break;
977           if (source[currentPosition + lookAhead] == '\n')
978             break;
979           if (source[currentPosition + lookAhead] == '`') {
980             currentPosition += lookAhead + 1;
981             break;
982           }
983         }
984       }
985       throw e; // rethrow
986     }
987     if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
988       // //$NON-NLS-?$ where ? is an
989       // int.
990       if (currentLine == null) {
991         currentLine = new NLSLine();
992         lines.add(currentLine);
993       }
994       currentLine.add(new StringLiteral(getCurrentTokenSourceString(), startPosition, currentPosition - 1));
995     }
996   }
997
998   public void consumeStringConstant() throws InvalidInputException {
999     try {
1000       // consume next character
1001       unicodeAsBackSlash = false;
1002       currentCharacter = source[currentPosition++];
1003       //                if (((currentCharacter = source[currentPosition++]) == '\\')
1004       //                  && (source[currentPosition] == 'u')) {
1005       //                  getNextUnicodeChar();
1006       //                } else {
1007       //                  if (withoutUnicodePtr != 0) {
1008       //                    withoutUnicodeBuffer[++withoutUnicodePtr] =
1009       //                      currentCharacter;
1010       //                  }
1011       //                }
1012       while (currentCharacter != '\'') {
1013         /** ** in PHP \r and \n are valid in string literals *** */
1014         //                  if ((currentCharacter == '\n')
1015         //                    || (currentCharacter == '\r')) {
1016         //                    // relocate if finding another quote fairly close: thus unicode
1017         // '/u000D' will be fully consumed
1018         //                    for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1019         //                      if (currentPosition + lookAhead == source.length)
1020         //                        break;
1021         //                      if (source[currentPosition + lookAhead] == '\n')
1022         //                        break;
1023         //                      if (source[currentPosition + lookAhead] == '\"') {
1024         //                        currentPosition += lookAhead + 1;
1025         //                        break;
1026         //                      }
1027         //                    }
1028         //                    throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1029         //                  }
1030         if (currentCharacter == '\\') {
1031           int escapeSize = currentPosition;
1032           boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
1033           //scanEscapeCharacter make a side effect on this value and we need
1034           // the previous value few lines down this one
1035           scanSingleQuotedEscapeCharacter();
1036           escapeSize = currentPosition - escapeSize;
1037           if (withoutUnicodePtr == 0) {
1038             //buffer all the entries that have been left aside....
1039             withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
1040             System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
1041             withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1042           } else { //overwrite the / in the buffer
1043             withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
1044             if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
1045               // where only one is correct
1046               withoutUnicodePtr--;
1047             }
1048           }
1049         }
1050         // consume next character
1051         unicodeAsBackSlash = false;
1052         currentCharacter = source[currentPosition++];
1053         //                  if (((currentCharacter = source[currentPosition++]) == '\\')
1054         //                    && (source[currentPosition] == 'u')) {
1055         //                    getNextUnicodeChar();
1056         //                  } else {
1057         if (withoutUnicodePtr != 0) {
1058           withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1059         }
1060         //                  }
1061       }
1062     } catch (IndexOutOfBoundsException e) {
1063       // reset end position for error reporting
1064       currentPosition -= 2;
1065       throw new InvalidInputException(UNTERMINATED_STRING);
1066     } catch (InvalidInputException e) {
1067       if (e.getMessage().equals(INVALID_ESCAPE)) {
1068         // relocate if finding another quote fairly close: thus unicode
1069         // '/u000D' will be fully consumed
1070         for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1071           if (currentPosition + lookAhead == source.length)
1072             break;
1073           if (source[currentPosition + lookAhead] == '\n')
1074             break;
1075           if (source[currentPosition + lookAhead] == '\'') {
1076             currentPosition += lookAhead + 1;
1077             break;
1078           }
1079         }
1080       }
1081       throw e; // rethrow
1082     }
1083     if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
1084       // //$NON-NLS-?$ where ? is an
1085       // int.
1086       if (currentLine == null) {
1087         currentLine = new NLSLine();
1088         lines.add(currentLine);
1089       }
1090       currentLine.add(new StringLiteral(getCurrentTokenSourceString(), startPosition, currentPosition - 1));
1091     }
1092   }
1093
1094   public void consumeStringLiteral() throws InvalidInputException {
1095     try {
1096       // consume next character
1097       unicodeAsBackSlash = false;
1098       currentCharacter = source[currentPosition++];
1099       //                if (((currentCharacter = source[currentPosition++]) == '\\')
1100       //                  && (source[currentPosition] == 'u')) {
1101       //                  getNextUnicodeChar();
1102       //                } else {
1103       //                  if (withoutUnicodePtr != 0) {
1104       //                    withoutUnicodeBuffer[++withoutUnicodePtr] =
1105       //                      currentCharacter;
1106       //                  }
1107       //                }
1108       while (currentCharacter != '"') {
1109         /** ** in PHP \r and \n are valid in string literals *** */
1110         //                  if ((currentCharacter == '\n')
1111         //                    || (currentCharacter == '\r')) {
1112         //                    // relocate if finding another quote fairly close: thus unicode
1113         // '/u000D' will be fully consumed
1114         //                    for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1115         //                      if (currentPosition + lookAhead == source.length)
1116         //                        break;
1117         //                      if (source[currentPosition + lookAhead] == '\n')
1118         //                        break;
1119         //                      if (source[currentPosition + lookAhead] == '\"') {
1120         //                        currentPosition += lookAhead + 1;
1121         //                        break;
1122         //                      }
1123         //                    }
1124         //                    throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1125         //                  }
1126         if (currentCharacter == '\\') {
1127           int escapeSize = currentPosition;
1128           boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
1129           //scanEscapeCharacter make a side effect on this value and we need
1130           // the previous value few lines down this one
1131           scanDoubleQuotedEscapeCharacter();
1132           escapeSize = currentPosition - escapeSize;
1133           if (withoutUnicodePtr == 0) {
1134             //buffer all the entries that have been left aside....
1135             withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
1136             System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
1137             withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1138           } else { //overwrite the / in the buffer
1139             withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
1140             if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
1141               // where only one is correct
1142               withoutUnicodePtr--;
1143             }
1144           }
1145         } else if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1146           if (recordLineSeparator) {
1147             pushLineSeparator();
1148           }
1149         }
1150         // consume next character
1151         unicodeAsBackSlash = false;
1152         currentCharacter = source[currentPosition++];
1153         //                  if (((currentCharacter = source[currentPosition++]) == '\\')
1154         //                    && (source[currentPosition] == 'u')) {
1155         //                    getNextUnicodeChar();
1156         //                  } else {
1157         if (withoutUnicodePtr != 0) {
1158           withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1159         }
1160         //                  }
1161       }
1162     } catch (IndexOutOfBoundsException e) {
1163       //    reset end position for error reporting
1164       currentPosition -= 2;
1165       throw new InvalidInputException(UNTERMINATED_STRING);
1166     } catch (InvalidInputException e) {
1167       if (e.getMessage().equals(INVALID_ESCAPE)) {
1168         // relocate if finding another quote fairly close: thus unicode
1169         // '/u000D' will be fully consumed
1170         for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1171           if (currentPosition + lookAhead == source.length)
1172             break;
1173           if (source[currentPosition + lookAhead] == '\n')
1174             break;
1175           if (source[currentPosition + lookAhead] == '\"') {
1176             currentPosition += lookAhead + 1;
1177             break;
1178           }
1179         }
1180       }
1181       throw e; // rethrow
1182     }
1183     if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
1184       // //$NON-NLS-?$ where ? is an
1185       // int.
1186       if (currentLine == null) {
1187         currentLine = new NLSLine();
1188         lines.add(currentLine);
1189       }
1190       currentLine.add(new StringLiteral(getCurrentTokenSourceString(), startPosition, currentPosition - 1));
1191     }
1192   }
1193
1194   public int getNextToken() throws InvalidInputException {
1195     if (!phpMode) {
1196       return getInlinedHTML(currentPosition);
1197     }
1198     if (phpMode) {
1199       this.wasAcr = false;
1200       if (diet) {
1201         jumpOverMethodBody();
1202         diet = false;
1203         return currentPosition > source.length ? TokenNameEOF : TokenNameRBRACE;
1204       }
1205       try {
1206         while (true) {
1207           withoutUnicodePtr = 0;
1208           //start with a new token
1209           char encapsedChar = ' ';
1210           if (!encapsedStringStack.isEmpty()) {
1211             encapsedChar = ((Character) encapsedStringStack.peek()).charValue();
1212           }
1213           if (encapsedChar != '$' && encapsedChar != ' ') {
1214             currentCharacter = source[currentPosition++];
1215             if (currentCharacter == encapsedChar) {
1216               switch (currentCharacter) {
1217               case '`':
1218                 return TokenNameEncapsedString0;
1219               case '\'':
1220                 return TokenNameEncapsedString1;
1221               case '"':
1222                 return TokenNameEncapsedString2;
1223               }
1224             }
1225             while (currentCharacter != encapsedChar) {
1226               /** ** in PHP \r and \n are valid in string literals *** */
1227               switch (currentCharacter) {
1228               case '\\':
1229                 int escapeSize = currentPosition;
1230                 boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
1231                 //scanEscapeCharacter make a side effect on this value and
1232                 // we need the previous value few lines down this one
1233                 scanDoubleQuotedEscapeCharacter();
1234                 escapeSize = currentPosition - escapeSize;
1235                 if (withoutUnicodePtr == 0) {
1236                   //buffer all the entries that have been left aside....
1237                   withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
1238                   System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
1239                   withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1240                 } else { //overwrite the / in the buffer
1241                   withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
1242                   if (backSlashAsUnicodeInString) { //there are TWO \ in
1243                     withoutUnicodePtr--;
1244                   }
1245                 }
1246                 break;
1247               case '\r':
1248               case '\n':
1249                 if (recordLineSeparator) {
1250                   pushLineSeparator();
1251                 }
1252                 break;
1253               case '$':
1254                 if (isPHPIdentifierStart(source[currentPosition]) || source[currentPosition] == '{') {
1255                   currentPosition--;
1256                   encapsedStringStack.push(new Character('$'));
1257                   return TokenNameSTRING;
1258                 }
1259                 break;
1260               case '{':
1261                 if (source[currentPosition] == '$') { // CURLY_OPEN
1262                   currentPosition--;
1263                   encapsedStringStack.push(new Character('$'));
1264                   return TokenNameSTRING;
1265                 }
1266               }
1267               // consume next character
1268               unicodeAsBackSlash = false;
1269               currentCharacter = source[currentPosition++];
1270               if (withoutUnicodePtr != 0) {
1271                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1272               }
1273               //                  }
1274             } // end while
1275             currentPosition--;
1276             return TokenNameSTRING;
1277           }
1278           // ---------Consume white space and handles startPosition---------
1279           int whiteStart = currentPosition;
1280           startPosition = currentPosition;
1281           currentCharacter = source[currentPosition++];
1282           if (encapsedChar == '$') {
1283             switch (currentCharacter) {
1284             case '\\':
1285               currentCharacter = source[currentPosition++];
1286               return TokenNameSTRING;
1287             case '{':
1288               if (encapsedChar == '$') {
1289                 if (getNextChar('$'))
1290                   return TokenNameLBRACE_DOLLAR;
1291               }
1292               return TokenNameLBRACE;
1293             case '}':
1294               return TokenNameRBRACE;
1295             case '[':
1296               return TokenNameLBRACKET;
1297             case ']':
1298               return TokenNameRBRACKET;
1299             case '\'':
1300               if (tokenizeStrings) {
1301                 consumeStringConstant();
1302                 return TokenNameStringSingleQuote;
1303               }
1304               return TokenNameEncapsedString1;
1305             case '"':
1306               return TokenNameEncapsedString2;
1307             case '`':
1308               if (tokenizeStrings) {
1309                 consumeStringInterpolated();
1310                 return TokenNameStringInterpolated;
1311               }
1312               return TokenNameEncapsedString0;
1313             case '-':
1314               if (getNextChar('>'))
1315                 return TokenNameMINUS_GREATER;
1316               return TokenNameSTRING;
1317             default:
1318               if (currentCharacter == '$') {
1319                 int oldPosition = currentPosition;
1320                 try {
1321                   currentCharacter = source[currentPosition++];
1322                   if (currentCharacter == '{') {
1323                     return TokenNameDOLLAR_LBRACE;
1324                   }
1325                   if (isPHPIdentifierStart(currentCharacter)) {
1326                     return scanIdentifierOrKeyword(true);
1327                   } else {
1328                     currentPosition = oldPosition;
1329                     return TokenNameSTRING;
1330                   }
1331                 } catch (IndexOutOfBoundsException e) {
1332                   currentPosition = oldPosition;
1333                   return TokenNameSTRING;
1334                 }
1335               }
1336               if (isPHPIdentifierStart(currentCharacter))
1337                 return scanIdentifierOrKeyword(false);
1338               if (Character.isDigit(currentCharacter))
1339                 return scanNumber(false);
1340               return TokenNameERROR;
1341             }
1342           }
1343           //          boolean isWhiteSpace;
1344
1345           while ((currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) {
1346             startPosition = currentPosition;
1347             currentCharacter = source[currentPosition++];
1348             //            if (((currentCharacter = source[currentPosition++]) == '\\')
1349             //              && (source[currentPosition] == 'u')) {
1350             //              isWhiteSpace = jumpOverUnicodeWhiteSpace();
1351             //            } else {
1352             if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1353               checkNonExternalizeString();
1354               if (recordLineSeparator) {
1355                 pushLineSeparator();
1356               } else {
1357                 currentLine = null;
1358               }
1359             }
1360             //            isWhiteSpace = (currentCharacter == ' ')
1361             //                || Character.isWhitespace(currentCharacter);
1362             //            }
1363           }
1364           if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) {
1365             // reposition scanner in case we are interested by spaces as tokens
1366             currentPosition--;
1367             startPosition = whiteStart;
1368             return TokenNameWHITESPACE;
1369           }
1370           //little trick to get out in the middle of a source compuation
1371           if (currentPosition > eofPosition)
1372             return TokenNameEOF;
1373           // ---------Identify the next token-------------
1374           switch (currentCharacter) {
1375           case '(':
1376             return getCastOrParen();
1377           case ')':
1378             return TokenNameRPAREN;
1379           case '{':
1380             return TokenNameLBRACE;
1381           case '}':
1382             return TokenNameRBRACE;
1383           case '[':
1384             return TokenNameLBRACKET;
1385           case ']':
1386             return TokenNameRBRACKET;
1387           case ';':
1388             return TokenNameSEMICOLON;
1389           case ',':
1390             return TokenNameCOMMA;
1391           case '.':
1392             if (getNextChar('='))
1393               return TokenNameDOT_EQUAL;
1394             if (getNextCharAsDigit())
1395               return scanNumber(true);
1396             return TokenNameDOT;
1397           case '+': {
1398             int test;
1399             if ((test = getNextChar('+', '=')) == 0)
1400               return TokenNamePLUS_PLUS;
1401             if (test > 0)
1402               return TokenNamePLUS_EQUAL;
1403             return TokenNamePLUS;
1404           }
1405           case '-': {
1406             int test;
1407             if ((test = getNextChar('-', '=')) == 0)
1408               return TokenNameMINUS_MINUS;
1409             if (test > 0)
1410               return TokenNameMINUS_EQUAL;
1411             if (getNextChar('>'))
1412               return TokenNameMINUS_GREATER;
1413             return TokenNameMINUS;
1414           }
1415           case '~':
1416             if (getNextChar('='))
1417               return TokenNameTWIDDLE_EQUAL;
1418             return TokenNameTWIDDLE;
1419           case '!':
1420             if (getNextChar('=')) {
1421               if (getNextChar('=')) {
1422                 return TokenNameNOT_EQUAL_EQUAL;
1423               }
1424               return TokenNameNOT_EQUAL;
1425             }
1426             return TokenNameNOT;
1427           case '*':
1428             if (getNextChar('='))
1429               return TokenNameMULTIPLY_EQUAL;
1430             return TokenNameMULTIPLY;
1431           case '%':
1432             if (getNextChar('='))
1433               return TokenNameREMAINDER_EQUAL;
1434             return TokenNameREMAINDER;
1435           case '<': {
1436             int oldPosition = currentPosition;
1437             try {
1438               currentCharacter = source[currentPosition++];
1439             } catch (IndexOutOfBoundsException e) {
1440               currentPosition = oldPosition;
1441               return TokenNameLESS;
1442             }
1443             switch (currentCharacter) {
1444             case '=':
1445               return TokenNameLESS_EQUAL;
1446             case '>':
1447               return TokenNameNOT_EQUAL;
1448             case '<':
1449               if (getNextChar('='))
1450                 return TokenNameLEFT_SHIFT_EQUAL;
1451               if (getNextChar('<')) {
1452                 currentCharacter = source[currentPosition++];
1453                 while (Character.isWhitespace(currentCharacter)) {
1454                   currentCharacter = source[currentPosition++];
1455                 }
1456                 int heredocStart = currentPosition - 1;
1457                 int heredocLength = 0;
1458                 if (isPHPIdentifierStart(currentCharacter)) {
1459                   currentCharacter = source[currentPosition++];
1460                 } else {
1461                   return TokenNameERROR;
1462                 }
1463                 while (isPHPIdentifierPart(currentCharacter)) {
1464                   currentCharacter = source[currentPosition++];
1465                 }
1466                 heredocLength = currentPosition - heredocStart - 1;
1467                 // heredoc end-tag determination
1468                 boolean endTag = true;
1469                 char ch;
1470                 do {
1471                   ch = source[currentPosition++];
1472                   if (ch == '\r' || ch == '\n') {
1473                     if (recordLineSeparator) {
1474                       pushLineSeparator();
1475                     } else {
1476                       currentLine = null;
1477                     }
1478                     for (int i = 0; i < heredocLength; i++) {
1479                       if (source[currentPosition + i] != source[heredocStart + i]) {
1480                         endTag = false;
1481                         break;
1482                       }
1483                     }
1484                     if (endTag) {
1485                       currentPosition += heredocLength - 1;
1486                       currentCharacter = source[currentPosition++];
1487                       break; // do...while loop
1488                     } else {
1489                       endTag = true;
1490                     }
1491                   }
1492                 } while (true);
1493                 return TokenNameHEREDOC;
1494               }
1495               return TokenNameLEFT_SHIFT;
1496             }
1497             currentPosition = oldPosition;
1498             return TokenNameLESS;
1499           }
1500           case '>': {
1501             int test;
1502             if ((test = getNextChar('=', '>')) == 0)
1503               return TokenNameGREATER_EQUAL;
1504             if (test > 0) {
1505               if ((test = getNextChar('=', '>')) == 0)
1506                 return TokenNameRIGHT_SHIFT_EQUAL;
1507               return TokenNameRIGHT_SHIFT;
1508             }
1509             return TokenNameGREATER;
1510           }
1511           case '=':
1512             if (getNextChar('=')) {
1513               if (getNextChar('=')) {
1514                 return TokenNameEQUAL_EQUAL_EQUAL;
1515               }
1516               return TokenNameEQUAL_EQUAL;
1517             }
1518             if (getNextChar('>'))
1519               return TokenNameEQUAL_GREATER;
1520             return TokenNameEQUAL;
1521           case '&': {
1522             int test;
1523             if ((test = getNextChar('&', '=')) == 0)
1524               return TokenNameAND_AND;
1525             if (test > 0)
1526               return TokenNameAND_EQUAL;
1527             return TokenNameAND;
1528           }
1529           case '|': {
1530             int test;
1531             if ((test = getNextChar('|', '=')) == 0)
1532               return TokenNameOR_OR;
1533             if (test > 0)
1534               return TokenNameOR_EQUAL;
1535             return TokenNameOR;
1536           }
1537           case '^':
1538             if (getNextChar('='))
1539               return TokenNameXOR_EQUAL;
1540             return TokenNameXOR;
1541           case '?':
1542             if (getNextChar('>')) {
1543               phpMode = false;
1544               if (currentPosition == source.length) {
1545                 phpMode = true;
1546                 return TokenNameINLINE_HTML;
1547               }
1548               return getInlinedHTML(currentPosition - 2);
1549             }
1550             return TokenNameQUESTION;
1551           case ':':
1552             if (getNextChar(':'))
1553               return TokenNamePAAMAYIM_NEKUDOTAYIM;
1554             return TokenNameCOLON;
1555           case '@':
1556             return TokenNameAT;
1557           case '\'':
1558             consumeStringConstant();
1559             return TokenNameStringSingleQuote;
1560           case '"':
1561             if (tokenizeStrings) {
1562               consumeStringLiteral();
1563               return TokenNameStringDoubleQuote;
1564             }
1565             return TokenNameEncapsedString2;
1566           case '`':
1567             if (tokenizeStrings) {
1568               consumeStringInterpolated();
1569               return TokenNameStringInterpolated;
1570             }
1571             return TokenNameEncapsedString0;
1572           case '#':
1573           case '/': {
1574             char startChar = currentCharacter;
1575             if (getNextChar('=') && startChar == '/') {
1576               return TokenNameDIVIDE_EQUAL;
1577             }
1578             int test;
1579             if ((startChar == '#') || (test = getNextChar('/', '*')) == 0) {
1580               //line comment
1581               this.lastCommentLinePosition = this.currentPosition;
1582               int endPositionForLineComment = 0;
1583               try { //get the next char
1584                 currentCharacter = source[currentPosition++];
1585                 //                    if (((currentCharacter = source[currentPosition++])
1586                 //                      == '\\')
1587                 //                      && (source[currentPosition] == 'u')) {
1588                 //                      //-------------unicode traitement ------------
1589                 //                      int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1590                 //                      currentPosition++;
1591                 //                      while (source[currentPosition] == 'u') {
1592                 //                        currentPosition++;
1593                 //                      }
1594                 //                      if ((c1 =
1595                 //                        Character.getNumericValue(source[currentPosition++]))
1596                 //                        > 15
1597                 //                        || c1 < 0
1598                 //                        || (c2 =
1599                 //                          Character.getNumericValue(source[currentPosition++]))
1600                 //                          > 15
1601                 //                        || c2 < 0
1602                 //                        || (c3 =
1603                 //                          Character.getNumericValue(source[currentPosition++]))
1604                 //                          > 15
1605                 //                        || c3 < 0
1606                 //                        || (c4 =
1607                 //                          Character.getNumericValue(source[currentPosition++]))
1608                 //                          > 15
1609                 //                        || c4 < 0) {
1610                 //                        throw new
1611                 // InvalidInputException(INVALID_UNICODE_ESCAPE);
1612                 //                      } else {
1613                 //                        currentCharacter =
1614                 //                          (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1615                 //                      }
1616                 //                    }
1617                 //handle the \\u case manually into comment
1618                 //                    if (currentCharacter == '\\') {
1619                 //                      if (source[currentPosition] == '\\')
1620                 //                        currentPosition++;
1621                 //                    } //jump over the \\
1622                 boolean isUnicode = false;
1623                 while (currentCharacter != '\r' && currentCharacter != '\n') {
1624                   this.lastCommentLinePosition = this.currentPosition;
1625                   if (currentCharacter == '?') {
1626                     if (getNextChar('>')) {
1627                       startPosition = currentPosition - 2;
1628                       phpMode = false;
1629                       return TokenNameINLINE_HTML;
1630                     }
1631                   }
1632                   //get the next char
1633                   isUnicode = false;
1634                   currentCharacter = source[currentPosition++];
1635                   //                      if (((currentCharacter = source[currentPosition++])
1636                   //                        == '\\')
1637                   //                        && (source[currentPosition] == 'u')) {
1638                   //                        isUnicode = true;
1639                   //                        //-------------unicode traitement ------------
1640                   //                        int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1641                   //                        currentPosition++;
1642                   //                        while (source[currentPosition] == 'u') {
1643                   //                          currentPosition++;
1644                   //                        }
1645                   //                        if ((c1 =
1646                   //                          Character.getNumericValue(source[currentPosition++]))
1647                   //                          > 15
1648                   //                          || c1 < 0
1649                   //                          || (c2 =
1650                   //                            Character.getNumericValue(
1651                   //                              source[currentPosition++]))
1652                   //                            > 15
1653                   //                          || c2 < 0
1654                   //                          || (c3 =
1655                   //                            Character.getNumericValue(
1656                   //                              source[currentPosition++]))
1657                   //                            > 15
1658                   //                          || c3 < 0
1659                   //                          || (c4 =
1660                   //                            Character.getNumericValue(
1661                   //                              source[currentPosition++]))
1662                   //                            > 15
1663                   //                          || c4 < 0) {
1664                   //                          throw new
1665                   // InvalidInputException(INVALID_UNICODE_ESCAPE);
1666                   //                        } else {
1667                   //                          currentCharacter =
1668                   //                            (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1669                   //                        }
1670                   //                      }
1671                   //handle the \\u case manually into comment
1672                   //                      if (currentCharacter == '\\') {
1673                   //                        if (source[currentPosition] == '\\')
1674                   //                          currentPosition++;
1675                   //                      } //jump over the \\
1676                 }
1677                 if (isUnicode) {
1678                   endPositionForLineComment = currentPosition - 6;
1679                 } else {
1680                   endPositionForLineComment = currentPosition - 1;
1681                 }
1682                 //                    recordComment(false);
1683                 recordComment(TokenNameCOMMENT_LINE);
1684                 if (this.taskTags != null)
1685                   checkTaskTag(this.startPosition, this.currentPosition);
1686                 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1687                   checkNonExternalizeString();
1688                   if (recordLineSeparator) {
1689                     if (isUnicode) {
1690                       pushUnicodeLineSeparator();
1691                     } else {
1692                       pushLineSeparator();
1693                     }
1694                   } else {
1695                     currentLine = null;
1696                   }
1697                 }
1698                 if (tokenizeComments) {
1699                   if (!isUnicode) {
1700                     currentPosition = endPositionForLineComment;
1701                     // reset one character behind
1702                   }
1703                   return TokenNameCOMMENT_LINE;
1704                 }
1705               } catch (IndexOutOfBoundsException e) { //an eof will them
1706                 // be generated
1707                 if (tokenizeComments) {
1708                   currentPosition--;
1709                   // reset one character behind
1710                   return TokenNameCOMMENT_LINE;
1711                 }
1712               }
1713               break;
1714             }
1715             if (test > 0) {
1716               //traditional and annotation comment
1717               boolean isJavadoc = false, star = false;
1718               // consume next character
1719               unicodeAsBackSlash = false;
1720               currentCharacter = source[currentPosition++];
1721               //                  if (((currentCharacter = source[currentPosition++]) ==
1722               // '\\')
1723               //                    && (source[currentPosition] == 'u')) {
1724               //                    getNextUnicodeChar();
1725               //                  } else {
1726               //                    if (withoutUnicodePtr != 0) {
1727               //                      withoutUnicodeBuffer[++withoutUnicodePtr] =
1728               //                        currentCharacter;
1729               //                    }
1730               //                  }
1731               if (currentCharacter == '*') {
1732                 isJavadoc = true;
1733                 star = true;
1734               }
1735               if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1736                 checkNonExternalizeString();
1737                 if (recordLineSeparator) {
1738                   pushLineSeparator();
1739                 } else {
1740                   currentLine = null;
1741                 }
1742               }
1743               try { //get the next char
1744                 currentCharacter = source[currentPosition++];
1745                 //                    if (((currentCharacter = source[currentPosition++])
1746                 //                      == '\\')
1747                 //                      && (source[currentPosition] == 'u')) {
1748                 //                      //-------------unicode traitement ------------
1749                 //                      getNextUnicodeChar();
1750                 //                    }
1751                 //handle the \\u case manually into comment
1752                 //                    if (currentCharacter == '\\') {
1753                 //                      if (source[currentPosition] == '\\')
1754                 //                        currentPosition++;
1755                 //                      //jump over the \\
1756                 //                    }
1757                 // empty comment is not a javadoc /**/
1758                 if (currentCharacter == '/') {
1759                   isJavadoc = false;
1760                 }
1761                 //loop until end of comment */
1762                 while ((currentCharacter != '/') || (!star)) {
1763                   if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1764                     checkNonExternalizeString();
1765                     if (recordLineSeparator) {
1766                       pushLineSeparator();
1767                     } else {
1768                       currentLine = null;
1769                     }
1770                   }
1771                   star = currentCharacter == '*';
1772                   //get next char
1773                   currentCharacter = source[currentPosition++];
1774                   //                      if (((currentCharacter = source[currentPosition++])
1775                   //                        == '\\')
1776                   //                        && (source[currentPosition] == 'u')) {
1777                   //                        //-------------unicode traitement ------------
1778                   //                        getNextUnicodeChar();
1779                   //                      }
1780                   //handle the \\u case manually into comment
1781                   //                      if (currentCharacter == '\\') {
1782                   //                        if (source[currentPosition] == '\\')
1783                   //                          currentPosition++;
1784                   //                      } //jump over the \\
1785                 }
1786                 //recordComment(isJavadoc);
1787                 if (isJavadoc) {
1788                   recordComment(TokenNameCOMMENT_PHPDOC);
1789                 } else {
1790                   recordComment(TokenNameCOMMENT_BLOCK);
1791                 }
1792
1793                 if (tokenizeComments) {
1794                   if (isJavadoc)
1795                     return TokenNameCOMMENT_PHPDOC;
1796                   return TokenNameCOMMENT_BLOCK;
1797                 }
1798
1799                 if (this.taskTags != null) {
1800                   checkTaskTag(this.startPosition, this.currentPosition);
1801                 }
1802               } catch (IndexOutOfBoundsException e) {
1803                 //                  reset end position for error reporting
1804                 currentPosition -= 2;
1805                 throw new InvalidInputException(UNTERMINATED_COMMENT);
1806               }
1807               break;
1808             }
1809             return TokenNameDIVIDE;
1810           }
1811           case '\u001a':
1812             if (atEnd())
1813               return TokenNameEOF;
1814             //the atEnd may not be <currentPosition == source.length> if
1815             // source is only some part of a real (external) stream
1816             throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
1817           default:
1818             if (currentCharacter == '$') {
1819               int oldPosition = currentPosition;
1820               try {
1821                 currentCharacter = source[currentPosition++];
1822                 if (isPHPIdentifierStart(currentCharacter)) {
1823                   return scanIdentifierOrKeyword(true);
1824                 } else {
1825                   currentPosition = oldPosition;
1826                   return TokenNameDOLLAR;
1827                 }
1828               } catch (IndexOutOfBoundsException e) {
1829                 currentPosition = oldPosition;
1830                 return TokenNameDOLLAR;
1831               }
1832             }
1833             if (isPHPIdentifierStart(currentCharacter))
1834               return scanIdentifierOrKeyword(false);
1835             if (Character.isDigit(currentCharacter))
1836               return scanNumber(false);
1837             return TokenNameERROR;
1838           }
1839         }
1840       } //-----------------end switch while try--------------------
1841       catch (IndexOutOfBoundsException e) {
1842       }
1843     }
1844     return TokenNameEOF;
1845   }
1846
1847   private int getInlinedHTML(int start) throws InvalidInputException {
1848     int token = getInlinedHTMLToken(start);
1849     if (token == TokenNameINLINE_HTML) {
1850       //                Stack stack = new Stack();
1851       //                // scan html for errors
1852       //                Source inlinedHTMLSource = new Source(new String(source, startPosition, currentPosition - startPosition));
1853       //                int lastPHPEndPos=0;
1854       //                for (Iterator i=inlinedHTMLSource.getNextTagIterator(0); i.hasNext();) {
1855       //                    Tag tag=(Tag)i.next();
1856       //                    
1857       //                    if (tag instanceof StartTag) {
1858       //                        StartTag startTag=(StartTag)tag;
1859       //                      // System.out.println("startTag: "+tag);
1860       //                        if (startTag.isServerTag()) {
1861       //                          // TODO : what to do with a server tag ?
1862       //                        } else {
1863       //                            // do whatever with HTML start tag
1864       //                            // use startTag.getElement() to find the element corresponding
1865       //                            // to this start tag which may be useful if you implement code
1866       //                            // folding etc
1867       //                                stack.push(startTag);
1868       //                        }
1869       //                    } else {
1870       //                        EndTag endTag=(EndTag)tag;
1871       //                        StartTag stag = (StartTag) stack.peek();
1872       //// System.out.println("endTag: "+tag);
1873       //                        // do whatever with HTML end tag.
1874       //                    }
1875       //                }
1876     }
1877     return token;
1878   }
1879
1880   /**
1881    * @return
1882    * @throws InvalidInputException
1883    */
1884   private int getInlinedHTMLToken(int start) throws InvalidInputException {
1885     if (currentPosition > source.length) {
1886       currentPosition = source.length;
1887       return TokenNameEOF;
1888     }
1889     startPosition = start;
1890     try {
1891       while (!phpMode) {
1892         currentCharacter = source[currentPosition++];
1893         if (currentCharacter == '<') {
1894           if (getNextChar('?')) {
1895             currentCharacter = source[currentPosition++];
1896             if ((currentCharacter != 'P') && (currentCharacter != 'p')) {
1897               currentPosition--;
1898               // (currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) {
1899               // <?
1900               if (ignorePHPOneLiner) {
1901                 if (lookAheadLinePHPTag() == TokenNameINLINE_HTML) {
1902                   phpMode = true;
1903                   return TokenNameINLINE_HTML;
1904                 }
1905               } else {
1906                 phpMode = true;
1907                 return TokenNameINLINE_HTML;
1908               }
1909             } else {
1910               //              boolean phpStart = (currentCharacter == 'P') || (currentCharacter == 'p');
1911               //              if (phpStart) {
1912               int test = getNextChar('H', 'h');
1913               if (test >= 0) {
1914                 test = getNextChar('P', 'p');
1915                 if (test >= 0) {
1916                   // <?PHP <?php
1917                   if (ignorePHPOneLiner) {
1918                     if (lookAheadLinePHPTag() == TokenNameINLINE_HTML) {
1919                       phpMode = true;
1920                       return TokenNameINLINE_HTML;
1921                     }
1922                   } else {
1923                     phpMode = true;
1924                     return TokenNameINLINE_HTML;
1925                   }
1926                 }
1927               }
1928               //              }
1929             }
1930           }
1931         }
1932         if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1933           if (recordLineSeparator) {
1934             pushLineSeparator();
1935           } else {
1936             currentLine = null;
1937           }
1938         }
1939       } //-----------------while--------------------
1940       phpMode = true;
1941       return TokenNameINLINE_HTML;
1942     } //-----------------try--------------------
1943     catch (IndexOutOfBoundsException e) {
1944       startPosition = start;
1945       currentPosition--;
1946     }
1947     phpMode = true;
1948     return TokenNameINLINE_HTML;
1949   }
1950
1951   /**
1952    * @return
1953    */
1954   private int lookAheadLinePHPTag() {
1955     // check if the PHP is only in this line (for CodeFormatter)
1956     int currentPositionInLine = currentPosition;
1957     char previousCharInLine = ' ';
1958     char currentCharInLine = ' ';
1959     boolean singleQuotedStringActive = false;
1960     boolean doubleQuotedStringActive = false;
1961
1962     try {
1963       // look ahead in this line
1964       while (true) {
1965         previousCharInLine = currentCharInLine;
1966         currentCharInLine = source[currentPositionInLine++];
1967         switch (currentCharInLine) {
1968         case '>':
1969           if (previousCharInLine == '?') {
1970             // update the scanner's current Position in the source
1971             currentPosition = currentPositionInLine;
1972             // use as "dummy" token
1973             return TokenNameEOF;
1974           }
1975           break;
1976         case '\"':
1977           if (doubleQuotedStringActive) {
1978             if (previousCharInLine != '\\') {
1979               doubleQuotedStringActive = false;
1980             }
1981           } else {
1982             if (!singleQuotedStringActive) {
1983               doubleQuotedStringActive = true;
1984             }
1985           }
1986           break;
1987         case '\'':
1988           if (singleQuotedStringActive) {
1989             if (previousCharInLine != '\\') {
1990               singleQuotedStringActive = false;
1991             }
1992           } else {
1993             if (!doubleQuotedStringActive) {
1994               singleQuotedStringActive = true;
1995             }
1996           }
1997           break;
1998         case '\n':
1999           phpMode = true;
2000           return TokenNameINLINE_HTML;
2001         case '#':
2002           if (!singleQuotedStringActive && !doubleQuotedStringActive) {
2003             phpMode = true;
2004             return TokenNameINLINE_HTML;
2005           }
2006           break;
2007         case '/':
2008           if (previousCharInLine == '/' && !singleQuotedStringActive && !doubleQuotedStringActive) {
2009             phpMode = true;
2010             return TokenNameINLINE_HTML;
2011           }
2012           break;
2013         case '*':
2014           if (previousCharInLine == '/' && !singleQuotedStringActive && !doubleQuotedStringActive) {
2015             phpMode = true;
2016             return TokenNameINLINE_HTML;
2017           }
2018           break;
2019         }
2020       }
2021     } catch (IndexOutOfBoundsException e) {
2022       phpMode = true;
2023       currentPosition = currentPositionInLine;
2024       return TokenNameINLINE_HTML;
2025     }
2026   }
2027
2028   //  public final void getNextUnicodeChar()
2029   //    throws IndexOutOfBoundsException, InvalidInputException {
2030   //    //VOID
2031   //    //handle the case of unicode.
2032   //    //when a unicode appears then we must use a buffer that holds char
2033   // internal values
2034   //    //At the end of this method currentCharacter holds the new visited char
2035   //    //and currentPosition points right next after it
2036   //
2037   //    //ALL getNextChar.... ARE OPTIMIZED COPIES
2038   //
2039   //    int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
2040   //    currentPosition++;
2041   //    while (source[currentPosition] == 'u') {
2042   //      currentPosition++;
2043   //      unicodeSize++;
2044   //    }
2045   //
2046   //    if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
2047   //      || c1 < 0
2048   //      || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
2049   //      || c2 < 0
2050   //      || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
2051   //      || c3 < 0
2052   //      || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
2053   //      || c4 < 0) {
2054   //      throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
2055   //    } else {
2056   //      currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2057   //      //need the unicode buffer
2058   //      if (withoutUnicodePtr == 0) {
2059   //        //buffer all the entries that have been left aside....
2060   //        withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
2061   //        System.arraycopy(
2062   //          source,
2063   //          startPosition,
2064   //          withoutUnicodeBuffer,
2065   //          1,
2066   //          withoutUnicodePtr);
2067   //      }
2068   //      //fill the buffer with the char
2069   //      withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2070   //    }
2071   //    unicodeAsBackSlash = currentCharacter == '\\';
2072   //  }
2073   /*
2074    * Tokenize a method body, assuming that curly brackets are properly balanced.
2075    */
2076   public final void jumpOverMethodBody() {
2077     this.wasAcr = false;
2078     int found = 1;
2079     try {
2080       while (true) { //loop for jumping over comments
2081         // ---------Consume white space and handles startPosition---------
2082         boolean isWhiteSpace;
2083         do {
2084           startPosition = currentPosition;
2085           currentCharacter = source[currentPosition++];
2086           //          if (((currentCharacter = source[currentPosition++]) == '\\')
2087           //            && (source[currentPosition] == 'u')) {
2088           //            isWhiteSpace = jumpOverUnicodeWhiteSpace();
2089           //          } else {
2090           if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2091             pushLineSeparator();
2092           isWhiteSpace = Character.isWhitespace(currentCharacter);
2093           //          }
2094         } while (isWhiteSpace);
2095         // -------consume token until } is found---------
2096         switch (currentCharacter) {
2097         case '{':
2098           found++;
2099           break;
2100         case '}':
2101           found--;
2102           if (found == 0)
2103             return;
2104           break;
2105         case '\'': {
2106           boolean test;
2107           test = getNextChar('\\');
2108           if (test) {
2109             try {
2110               scanDoubleQuotedEscapeCharacter();
2111             } catch (InvalidInputException ex) {
2112             }
2113             ;
2114           } else {
2115             //                try { // consume next character
2116             unicodeAsBackSlash = false;
2117             currentCharacter = source[currentPosition++];
2118             //                  if (((currentCharacter = source[currentPosition++]) == '\\')
2119             //                    && (source[currentPosition] == 'u')) {
2120             //                    getNextUnicodeChar();
2121             //                  } else {
2122             if (withoutUnicodePtr != 0) {
2123               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2124             }
2125             //                  }
2126             //                } catch (InvalidInputException ex) {
2127             //                };
2128           }
2129           getNextChar('\'');
2130           break;
2131         }
2132         case '"':
2133           try {
2134             //              try { // consume next character
2135             unicodeAsBackSlash = false;
2136             currentCharacter = source[currentPosition++];
2137             //                if (((currentCharacter = source[currentPosition++]) == '\\')
2138             //                  && (source[currentPosition] == 'u')) {
2139             //                  getNextUnicodeChar();
2140             //                } else {
2141             if (withoutUnicodePtr != 0) {
2142               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2143             }
2144             //                }
2145             //              } catch (InvalidInputException ex) {
2146             //              };
2147             while (currentCharacter != '"') {
2148               if (currentCharacter == '\r') {
2149                 if (source[currentPosition] == '\n')
2150                   currentPosition++;
2151                 break;
2152                 // the string cannot go further that the line
2153               }
2154               if (currentCharacter == '\n') {
2155                 break;
2156                 // the string cannot go further that the line
2157               }
2158               if (currentCharacter == '\\') {
2159                 try {
2160                   scanDoubleQuotedEscapeCharacter();
2161                 } catch (InvalidInputException ex) {
2162                 }
2163                 ;
2164               }
2165               //                try { // consume next character
2166               unicodeAsBackSlash = false;
2167               currentCharacter = source[currentPosition++];
2168               //                  if (((currentCharacter = source[currentPosition++]) == '\\')
2169               //                    && (source[currentPosition] == 'u')) {
2170               //                    getNextUnicodeChar();
2171               //                  } else {
2172               if (withoutUnicodePtr != 0) {
2173                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2174               }
2175               //                  }
2176               //                } catch (InvalidInputException ex) {
2177               //                };
2178             }
2179           } catch (IndexOutOfBoundsException e) {
2180             return;
2181           }
2182           break;
2183         case '/': {
2184           int test;
2185           if ((test = getNextChar('/', '*')) == 0) {
2186             //line comment
2187             try {
2188               //get the next char
2189               currentCharacter = source[currentPosition++];
2190               //                  if (((currentCharacter = source[currentPosition++]) ==
2191               // '\\')
2192               //                    && (source[currentPosition] == 'u')) {
2193               //                    //-------------unicode traitement ------------
2194               //                    int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2195               //                    currentPosition++;
2196               //                    while (source[currentPosition] == 'u') {
2197               //                      currentPosition++;
2198               //                    }
2199               //                    if ((c1 =
2200               //                      Character.getNumericValue(source[currentPosition++]))
2201               //                      > 15
2202               //                      || c1 < 0
2203               //                      || (c2 =
2204               //                        Character.getNumericValue(source[currentPosition++]))
2205               //                        > 15
2206               //                      || c2 < 0
2207               //                      || (c3 =
2208               //                        Character.getNumericValue(source[currentPosition++]))
2209               //                        > 15
2210               //                      || c3 < 0
2211               //                      || (c4 =
2212               //                        Character.getNumericValue(source[currentPosition++]))
2213               //                        > 15
2214               //                      || c4 < 0) {
2215               //                      //error don't care of the value
2216               //                      currentCharacter = 'A';
2217               //                    } //something different from \n and \r
2218               //                    else {
2219               //                      currentCharacter =
2220               //                        (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2221               //                    }
2222               //                  }
2223               while (currentCharacter != '\r' && currentCharacter != '\n') {
2224                 //get the next char
2225                 currentCharacter = source[currentPosition++];
2226                 //                    if (((currentCharacter = source[currentPosition++])
2227                 //                      == '\\')
2228                 //                      && (source[currentPosition] == 'u')) {
2229                 //                      //-------------unicode traitement ------------
2230                 //                      int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2231                 //                      currentPosition++;
2232                 //                      while (source[currentPosition] == 'u') {
2233                 //                        currentPosition++;
2234                 //                      }
2235                 //                      if ((c1 =
2236                 //                        Character.getNumericValue(source[currentPosition++]))
2237                 //                        > 15
2238                 //                        || c1 < 0
2239                 //                        || (c2 =
2240                 //                          Character.getNumericValue(source[currentPosition++]))
2241                 //                          > 15
2242                 //                        || c2 < 0
2243                 //                        || (c3 =
2244                 //                          Character.getNumericValue(source[currentPosition++]))
2245                 //                          > 15
2246                 //                        || c3 < 0
2247                 //                        || (c4 =
2248                 //                          Character.getNumericValue(source[currentPosition++]))
2249                 //                          > 15
2250                 //                        || c4 < 0) {
2251                 //                        //error don't care of the value
2252                 //                        currentCharacter = 'A';
2253                 //                      } //something different from \n and \r
2254                 //                      else {
2255                 //                        currentCharacter =
2256                 //                          (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2257                 //                      }
2258                 //                    }
2259               }
2260               if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2261                 pushLineSeparator();
2262             } catch (IndexOutOfBoundsException e) {
2263             } //an eof will them be generated
2264             break;
2265           }
2266           if (test > 0) {
2267             //traditional and annotation comment
2268             boolean star = false;
2269             //                try { // consume next character
2270             unicodeAsBackSlash = false;
2271             currentCharacter = source[currentPosition++];
2272             //                  if (((currentCharacter = source[currentPosition++]) == '\\')
2273             //                    && (source[currentPosition] == 'u')) {
2274             //                    getNextUnicodeChar();
2275             //                  } else {
2276             if (withoutUnicodePtr != 0) {
2277               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2278             }
2279             //                  };
2280             //                } catch (InvalidInputException ex) {
2281             //                };
2282             if (currentCharacter == '*') {
2283               star = true;
2284             }
2285             if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2286               pushLineSeparator();
2287             try { //get the next char
2288               currentCharacter = source[currentPosition++];
2289               //                  if (((currentCharacter = source[currentPosition++]) ==
2290               // '\\')
2291               //                    && (source[currentPosition] == 'u')) {
2292               //                    //-------------unicode traitement ------------
2293               //                    int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2294               //                    currentPosition++;
2295               //                    while (source[currentPosition] == 'u') {
2296               //                      currentPosition++;
2297               //                    }
2298               //                    if ((c1 =
2299               //                      Character.getNumericValue(source[currentPosition++]))
2300               //                      > 15
2301               //                      || c1 < 0
2302               //                      || (c2 =
2303               //                        Character.getNumericValue(source[currentPosition++]))
2304               //                        > 15
2305               //                      || c2 < 0
2306               //                      || (c3 =
2307               //                        Character.getNumericValue(source[currentPosition++]))
2308               //                        > 15
2309               //                      || c3 < 0
2310               //                      || (c4 =
2311               //                        Character.getNumericValue(source[currentPosition++]))
2312               //                        > 15
2313               //                      || c4 < 0) {
2314               //                      //error don't care of the value
2315               //                      currentCharacter = 'A';
2316               //                    } //something different from * and /
2317               //                    else {
2318               //                      currentCharacter =
2319               //                        (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2320               //                    }
2321               //                  }
2322               //loop until end of comment */
2323               while ((currentCharacter != '/') || (!star)) {
2324                 if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2325                   pushLineSeparator();
2326                 star = currentCharacter == '*';
2327                 //get next char
2328                 currentCharacter = source[currentPosition++];
2329                 //                    if (((currentCharacter = source[currentPosition++])
2330                 //                      == '\\')
2331                 //                      && (source[currentPosition] == 'u')) {
2332                 //                      //-------------unicode traitement ------------
2333                 //                      int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2334                 //                      currentPosition++;
2335                 //                      while (source[currentPosition] == 'u') {
2336                 //                        currentPosition++;
2337                 //                      }
2338                 //                      if ((c1 =
2339                 //                        Character.getNumericValue(source[currentPosition++]))
2340                 //                        > 15
2341                 //                        || c1 < 0
2342                 //                        || (c2 =
2343                 //                          Character.getNumericValue(source[currentPosition++]))
2344                 //                          > 15
2345                 //                        || c2 < 0
2346                 //                        || (c3 =
2347                 //                          Character.getNumericValue(source[currentPosition++]))
2348                 //                          > 15
2349                 //                        || c3 < 0
2350                 //                        || (c4 =
2351                 //                          Character.getNumericValue(source[currentPosition++]))
2352                 //                          > 15
2353                 //                        || c4 < 0) {
2354                 //                        //error don't care of the value
2355                 //                        currentCharacter = 'A';
2356                 //                      } //something different from * and /
2357                 //                      else {
2358                 //                        currentCharacter =
2359                 //                          (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2360                 //                      }
2361                 //                    }
2362               }
2363             } catch (IndexOutOfBoundsException e) {
2364               return;
2365             }
2366             break;
2367           }
2368           break;
2369         }
2370         default:
2371           if (isPHPIdentifierStart(currentCharacter) || currentCharacter == '$') {
2372             try {
2373               scanIdentifierOrKeyword((currentCharacter == '$'));
2374             } catch (InvalidInputException ex) {
2375             }
2376             ;
2377             break;
2378           }
2379           if (Character.isDigit(currentCharacter)) {
2380             try {
2381               scanNumber(false);
2382             } catch (InvalidInputException ex) {
2383             }
2384             ;
2385             break;
2386           }
2387         }
2388       }
2389       //-----------------end switch while try--------------------
2390     } catch (IndexOutOfBoundsException e) {
2391     } catch (InvalidInputException e) {
2392     }
2393     return;
2394   }
2395
2396   //  public final boolean jumpOverUnicodeWhiteSpace()
2397   //    throws InvalidInputException {
2398   //    //BOOLEAN
2399   //    //handle the case of unicode. Jump over the next whiteSpace
2400   //    //making startPosition pointing on the next available char
2401   //    //On false, the currentCharacter is filled up with a potential
2402   //    //correct char
2403   //
2404   //    try {
2405   //      this.wasAcr = false;
2406   //      int c1, c2, c3, c4;
2407   //      int unicodeSize = 6;
2408   //      currentPosition++;
2409   //      while (source[currentPosition] == 'u') {
2410   //        currentPosition++;
2411   //        unicodeSize++;
2412   //      }
2413   //
2414   //      if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
2415   //        || c1 < 0)
2416   //        || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
2417   //          || c2 < 0)
2418   //        || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
2419   //          || c3 < 0)
2420   //        || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
2421   //          || c4 < 0)) {
2422   //        throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
2423   //      }
2424   //
2425   //      currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2426   //      if (recordLineSeparator
2427   //        && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2428   //        pushLineSeparator();
2429   //      if (Character.isWhitespace(currentCharacter))
2430   //        return true;
2431   //
2432   //      //buffer the new char which is not a white space
2433   //      withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2434   //      //withoutUnicodePtr == 1 is true here
2435   //      return false;
2436   //    } catch (IndexOutOfBoundsException e) {
2437   //      throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
2438   //    }
2439   //  }
2440   public final int[] getLineEnds() {
2441     //return a bounded copy of this.lineEnds
2442     int[] copy;
2443     System.arraycopy(lineEnds, 0, copy = new int[linePtr + 1], 0, linePtr + 1);
2444     return copy;
2445   }
2446
2447   public char[] getSource() {
2448     return this.source;
2449   }
2450
2451   public static boolean isIdentifierOrKeyword(int token) {
2452     return (token == TokenNameIdentifier) || (token > TokenNameKEYWORD);
2453   }
2454
2455   final char[] optimizedCurrentTokenSource1() {
2456     //return always the same char[] build only once
2457     //optimization at no speed cost of 99.5 % of the singleCharIdentifier
2458     char charOne = source[startPosition];
2459     switch (charOne) {
2460     case 'a':
2461       return charArray_a;
2462     case 'b':
2463       return charArray_b;
2464     case 'c':
2465       return charArray_c;
2466     case 'd':
2467       return charArray_d;
2468     case 'e':
2469       return charArray_e;
2470     case 'f':
2471       return charArray_f;
2472     case 'g':
2473       return charArray_g;
2474     case 'h':
2475       return charArray_h;
2476     case 'i':
2477       return charArray_i;
2478     case 'j':
2479       return charArray_j;
2480     case 'k':
2481       return charArray_k;
2482     case 'l':
2483       return charArray_l;
2484     case 'm':
2485       return charArray_m;
2486     case 'n':
2487       return charArray_n;
2488     case 'o':
2489       return charArray_o;
2490     case 'p':
2491       return charArray_p;
2492     case 'q':
2493       return charArray_q;
2494     case 'r':
2495       return charArray_r;
2496     case 's':
2497       return charArray_s;
2498     case 't':
2499       return charArray_t;
2500     case 'u':
2501       return charArray_u;
2502     case 'v':
2503       return charArray_v;
2504     case 'w':
2505       return charArray_w;
2506     case 'x':
2507       return charArray_x;
2508     case 'y':
2509       return charArray_y;
2510     case 'z':
2511       return charArray_z;
2512     default:
2513       return new char[] { charOne };
2514     }
2515   }
2516
2517   final char[] optimizedCurrentTokenSource2() {
2518     char c0, c1;
2519     c0 = source[startPosition];
2520     c1 = source[startPosition + 1];
2521     if (c0 == '$') {
2522       //return always the same char[] build only once
2523       //optimization at no speed cost of 99.5 % of the singleCharIdentifier
2524       switch (c1) {
2525       case 'a':
2526         return charArray_va;
2527       case 'b':
2528         return charArray_vb;
2529       case 'c':
2530         return charArray_vc;
2531       case 'd':
2532         return charArray_vd;
2533       case 'e':
2534         return charArray_ve;
2535       case 'f':
2536         return charArray_vf;
2537       case 'g':
2538         return charArray_vg;
2539       case 'h':
2540         return charArray_vh;
2541       case 'i':
2542         return charArray_vi;
2543       case 'j':
2544         return charArray_vj;
2545       case 'k':
2546         return charArray_vk;
2547       case 'l':
2548         return charArray_vl;
2549       case 'm':
2550         return charArray_vm;
2551       case 'n':
2552         return charArray_vn;
2553       case 'o':
2554         return charArray_vo;
2555       case 'p':
2556         return charArray_vp;
2557       case 'q':
2558         return charArray_vq;
2559       case 'r':
2560         return charArray_vr;
2561       case 's':
2562         return charArray_vs;
2563       case 't':
2564         return charArray_vt;
2565       case 'u':
2566         return charArray_vu;
2567       case 'v':
2568         return charArray_vv;
2569       case 'w':
2570         return charArray_vw;
2571       case 'x':
2572         return charArray_vx;
2573       case 'y':
2574         return charArray_vy;
2575       case 'z':
2576         return charArray_vz;
2577       }
2578     }
2579     //try to return the same char[] build only once
2580     int hash = ((c0 << 6) + c1) % TableSize;
2581     char[][] table = charArray_length[0][hash];
2582     int i = newEntry2;
2583     while (++i < InternalTableSize) {
2584       char[] charArray = table[i];
2585       if ((c0 == charArray[0]) && (c1 == charArray[1]))
2586         return charArray;
2587     }
2588     //---------other side---------
2589     i = -1;
2590     int max = newEntry2;
2591     while (++i <= max) {
2592       char[] charArray = table[i];
2593       if ((c0 == charArray[0]) && (c1 == charArray[1]))
2594         return charArray;
2595     }
2596     //--------add the entry-------
2597     if (++max >= InternalTableSize)
2598       max = 0;
2599     char[] r;
2600     table[max] = (r = new char[] { c0, c1 });
2601     newEntry2 = max;
2602     return r;
2603   }
2604
2605   final char[] optimizedCurrentTokenSource3() {
2606     //try to return the same char[] build only once
2607     char c0, c1, c2;
2608     int hash = (((c0 = source[startPosition]) << 12) + ((c1 = source[startPosition + 1]) << 6) + (c2 = source[startPosition + 2]))
2609         % TableSize;
2610     char[][] table = charArray_length[1][hash];
2611     int i = newEntry3;
2612     while (++i < InternalTableSize) {
2613       char[] charArray = table[i];
2614       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
2615         return charArray;
2616     }
2617     //---------other side---------
2618     i = -1;
2619     int max = newEntry3;
2620     while (++i <= max) {
2621       char[] charArray = table[i];
2622       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
2623         return charArray;
2624     }
2625     //--------add the entry-------
2626     if (++max >= InternalTableSize)
2627       max = 0;
2628     char[] r;
2629     table[max] = (r = new char[] { c0, c1, c2 });
2630     newEntry3 = max;
2631     return r;
2632   }
2633
2634   final char[] optimizedCurrentTokenSource4() {
2635     //try to return the same char[] build only once
2636     char c0, c1, c2, c3;
2637     long hash = ((((long) (c0 = source[startPosition])) << 18) + ((c1 = source[startPosition + 1]) << 12)
2638         + ((c2 = source[startPosition + 2]) << 6) + (c3 = source[startPosition + 3]))
2639         % TableSize;
2640     char[][] table = charArray_length[2][(int) hash];
2641     int i = newEntry4;
2642     while (++i < InternalTableSize) {
2643       char[] charArray = table[i];
2644       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]))
2645         return charArray;
2646     }
2647     //---------other side---------
2648     i = -1;
2649     int max = newEntry4;
2650     while (++i <= max) {
2651       char[] charArray = table[i];
2652       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]))
2653         return charArray;
2654     }
2655     //--------add the entry-------
2656     if (++max >= InternalTableSize)
2657       max = 0;
2658     char[] r;
2659     table[max] = (r = new char[] { c0, c1, c2, c3 });
2660     newEntry4 = max;
2661     return r;
2662   }
2663
2664   final char[] optimizedCurrentTokenSource5() {
2665     //try to return the same char[] build only once
2666     char c0, c1, c2, c3, c4;
2667     long hash = ((((long) (c0 = source[startPosition])) << 24) + (((long) (c1 = source[startPosition + 1])) << 18)
2668         + ((c2 = source[startPosition + 2]) << 12) + ((c3 = source[startPosition + 3]) << 6) + (c4 = source[startPosition + 4]))
2669         % TableSize;
2670     char[][] table = charArray_length[3][(int) hash];
2671     int i = newEntry5;
2672     while (++i < InternalTableSize) {
2673       char[] charArray = table[i];
2674       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4]))
2675         return charArray;
2676     }
2677     //---------other side---------
2678     i = -1;
2679     int max = newEntry5;
2680     while (++i <= max) {
2681       char[] charArray = table[i];
2682       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4]))
2683         return charArray;
2684     }
2685     //--------add the entry-------
2686     if (++max >= InternalTableSize)
2687       max = 0;
2688     char[] r;
2689     table[max] = (r = new char[] { c0, c1, c2, c3, c4 });
2690     newEntry5 = max;
2691     return r;
2692   }
2693
2694   final char[] optimizedCurrentTokenSource6() {
2695     //try to return the same char[] build only once
2696     char c0, c1, c2, c3, c4, c5;
2697     long hash = ((((long) (c0 = source[startPosition])) << 32) + (((long) (c1 = source[startPosition + 1])) << 24)
2698         + (((long) (c2 = source[startPosition + 2])) << 18) + ((c3 = source[startPosition + 3]) << 12)
2699         + ((c4 = source[startPosition + 4]) << 6) + (c5 = source[startPosition + 5]))
2700         % TableSize;
2701     char[][] table = charArray_length[4][(int) hash];
2702     int i = newEntry6;
2703     while (++i < InternalTableSize) {
2704       char[] charArray = table[i];
2705       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4])
2706           && (c5 == charArray[5]))
2707         return charArray;
2708     }
2709     //---------other side---------
2710     i = -1;
2711     int max = newEntry6;
2712     while (++i <= max) {
2713       char[] charArray = table[i];
2714       if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]) && (c3 == charArray[3]) && (c4 == charArray[4])
2715           && (c5 == charArray[5]))
2716         return charArray;
2717     }
2718     //--------add the entry-------
2719     if (++max >= InternalTableSize)
2720       max = 0;
2721     char[] r;
2722     table[max] = (r = new char[] { c0, c1, c2, c3, c4, c5 });
2723     newEntry6 = max;
2724     return r;
2725   }
2726
2727   public final void pushLineSeparator() throws InvalidInputException {
2728     //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
2729     final int INCREMENT = 250;
2730     if (this.checkNonExternalizedStringLiterals) {
2731       // reinitialize the current line for non externalize strings purpose
2732       currentLine = null;
2733     }
2734     //currentCharacter is at position currentPosition-1
2735     // cr 000D
2736     if (currentCharacter == '\r') {
2737       int separatorPos = currentPosition - 1;
2738       if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2739         return;
2740       //System.out.println("CR-" + separatorPos);
2741       try {
2742         lineEnds[++linePtr] = separatorPos;
2743       } catch (IndexOutOfBoundsException e) {
2744         //linePtr value is correct
2745         int oldLength = lineEnds.length;
2746         int[] old = lineEnds;
2747         lineEnds = new int[oldLength + INCREMENT];
2748         System.arraycopy(old, 0, lineEnds, 0, oldLength);
2749         lineEnds[linePtr] = separatorPos;
2750       }
2751       // look-ahead for merged cr+lf
2752       try {
2753         if (source[currentPosition] == '\n') {
2754           //System.out.println("look-ahead LF-" + currentPosition);
2755           lineEnds[linePtr] = currentPosition;
2756           currentPosition++;
2757           wasAcr = false;
2758         } else {
2759           wasAcr = true;
2760         }
2761       } catch (IndexOutOfBoundsException e) {
2762         wasAcr = true;
2763       }
2764     } else {
2765       // lf 000A
2766       if (currentCharacter == '\n') {
2767         //must merge eventual cr followed by lf
2768         if (wasAcr && (lineEnds[linePtr] == (currentPosition - 2))) {
2769           //System.out.println("merge LF-" + (currentPosition - 1));
2770           lineEnds[linePtr] = currentPosition - 1;
2771         } else {
2772           int separatorPos = currentPosition - 1;
2773           if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2774             return;
2775           // System.out.println("LF-" + separatorPos);
2776           try {
2777             lineEnds[++linePtr] = separatorPos;
2778           } catch (IndexOutOfBoundsException e) {
2779             //linePtr value is correct
2780             int oldLength = lineEnds.length;
2781             int[] old = lineEnds;
2782             lineEnds = new int[oldLength + INCREMENT];
2783             System.arraycopy(old, 0, lineEnds, 0, oldLength);
2784             lineEnds[linePtr] = separatorPos;
2785           }
2786         }
2787         wasAcr = false;
2788       }
2789     }
2790   }
2791
2792   public final void pushUnicodeLineSeparator() {
2793     // isUnicode means that the \r or \n has been read as a unicode character
2794     //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
2795     final int INCREMENT = 250;
2796     //currentCharacter is at position currentPosition-1
2797     if (this.checkNonExternalizedStringLiterals) {
2798       // reinitialize the current line for non externalize strings purpose
2799       currentLine = null;
2800     }
2801     // cr 000D
2802     if (currentCharacter == '\r') {
2803       int separatorPos = currentPosition - 6;
2804       if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2805         return;
2806       //System.out.println("CR-" + separatorPos);
2807       try {
2808         lineEnds[++linePtr] = separatorPos;
2809       } catch (IndexOutOfBoundsException e) {
2810         //linePtr value is correct
2811         int oldLength = lineEnds.length;
2812         int[] old = lineEnds;
2813         lineEnds = new int[oldLength + INCREMENT];
2814         System.arraycopy(old, 0, lineEnds, 0, oldLength);
2815         lineEnds[linePtr] = separatorPos;
2816       }
2817       // look-ahead for merged cr+lf
2818       if (source[currentPosition] == '\n') {
2819         //System.out.println("look-ahead LF-" + currentPosition);
2820         lineEnds[linePtr] = currentPosition;
2821         currentPosition++;
2822         wasAcr = false;
2823       } else {
2824         wasAcr = true;
2825       }
2826     } else {
2827       // lf 000A
2828       if (currentCharacter == '\n') {
2829         //must merge eventual cr followed by lf
2830         if (wasAcr && (lineEnds[linePtr] == (currentPosition - 7))) {
2831           //System.out.println("merge LF-" + (currentPosition - 1));
2832           lineEnds[linePtr] = currentPosition - 6;
2833         } else {
2834           int separatorPos = currentPosition - 6;
2835           if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2836             return;
2837           // System.out.println("LF-" + separatorPos);
2838           try {
2839             lineEnds[++linePtr] = separatorPos;
2840           } catch (IndexOutOfBoundsException e) {
2841             //linePtr value is correct
2842             int oldLength = lineEnds.length;
2843             int[] old = lineEnds;
2844             lineEnds = new int[oldLength + INCREMENT];
2845             System.arraycopy(old, 0, lineEnds, 0, oldLength);
2846             lineEnds[linePtr] = separatorPos;
2847           }
2848         }
2849         wasAcr = false;
2850       }
2851     }
2852   }
2853
2854   public void recordComment(int token) {
2855     // compute position
2856     int stopPosition = this.currentPosition;
2857     switch (token) {
2858     case TokenNameCOMMENT_LINE:
2859       stopPosition = -this.lastCommentLinePosition;
2860       break;
2861     case TokenNameCOMMENT_BLOCK:
2862       stopPosition = -this.currentPosition;
2863       break;
2864     }
2865
2866     // a new comment is recorded
2867     int length = this.commentStops.length;
2868     if (++this.commentPtr >= length) {
2869       System.arraycopy(this.commentStops, 0, this.commentStops = new int[length + 30], 0, length);
2870       //grows the positions buffers too
2871       System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[length + 30], 0, length);
2872     }
2873     this.commentStops[this.commentPtr] = stopPosition;
2874     this.commentStarts[this.commentPtr] = this.startPosition;
2875   }
2876
2877   //  public final void recordComment(boolean isJavadoc) {
2878   //    // a new annotation comment is recorded
2879   //    try {
2880   //      commentStops[++commentPtr] = isJavadoc
2881   //          ? currentPosition
2882   //          : -currentPosition;
2883   //    } catch (IndexOutOfBoundsException e) {
2884   //      int oldStackLength = commentStops.length;
2885   //      int[] oldStack = commentStops;
2886   //      commentStops = new int[oldStackLength + 30];
2887   //      System.arraycopy(oldStack, 0, commentStops, 0, oldStackLength);
2888   //      commentStops[commentPtr] = isJavadoc ? currentPosition : -currentPosition;
2889   //      //grows the positions buffers too
2890   //      int[] old = commentStarts;
2891   //      commentStarts = new int[oldStackLength + 30];
2892   //      System.arraycopy(old, 0, commentStarts, 0, oldStackLength);
2893   //    }
2894   //    //the buffer is of a correct size here
2895   //    commentStarts[commentPtr] = startPosition;
2896   //  }
2897   public void resetTo(int begin, int end) {
2898     //reset the scanner to a given position where it may rescan again
2899     diet = false;
2900     initialPosition = startPosition = currentPosition = begin;
2901     eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
2902     commentPtr = -1; // reset comment stack
2903   }
2904
2905   public final void scanSingleQuotedEscapeCharacter() throws InvalidInputException {
2906     // the string with "\\u" is a legal string of two chars \ and u
2907     //thus we use a direct access to the source (for regular cases).
2908     //    if (unicodeAsBackSlash) {
2909     //      // consume next character
2910     //      unicodeAsBackSlash = false;
2911     //      if (((currentCharacter = source[currentPosition++]) == '\\')
2912     //        && (source[currentPosition] == 'u')) {
2913     //        getNextUnicodeChar();
2914     //      } else {
2915     //        if (withoutUnicodePtr != 0) {
2916     //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2917     //        }
2918     //      }
2919     //    } else
2920     currentCharacter = source[currentPosition++];
2921     switch (currentCharacter) {
2922     case '\'':
2923       currentCharacter = '\'';
2924       break;
2925     case '\\':
2926       currentCharacter = '\\';
2927       break;
2928     default:
2929       currentCharacter = '\\';
2930       currentPosition--;
2931     }
2932   }
2933
2934   public final void scanDoubleQuotedEscapeCharacter() throws InvalidInputException {
2935     // the string with "\\u" is a legal string of two chars \ and u
2936     //thus we use a direct access to the source (for regular cases).
2937     //    if (unicodeAsBackSlash) {
2938     //      // consume next character
2939     //      unicodeAsBackSlash = false;
2940     //      if (((currentCharacter = source[currentPosition++]) == '\\')
2941     //        && (source[currentPosition] == 'u')) {
2942     //        getNextUnicodeChar();
2943     //      } else {
2944     //        if (withoutUnicodePtr != 0) {
2945     //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2946     //        }
2947     //      }
2948     //    } else
2949     currentCharacter = source[currentPosition++];
2950     switch (currentCharacter) {
2951     //      case 'b' :
2952     //        currentCharacter = '\b';
2953     //        break;
2954     case 't':
2955       currentCharacter = '\t';
2956       break;
2957     case 'n':
2958       currentCharacter = '\n';
2959       break;
2960     //      case 'f' :
2961     //        currentCharacter = '\f';
2962     //        break;
2963     case 'r':
2964       currentCharacter = '\r';
2965       break;
2966     case '\"':
2967       currentCharacter = '\"';
2968       break;
2969     case '\'':
2970       currentCharacter = '\'';
2971       break;
2972     case '\\':
2973       currentCharacter = '\\';
2974       break;
2975     case '$':
2976       currentCharacter = '$';
2977       break;
2978     default:
2979       // -----------octal escape--------------
2980       // OctalDigit
2981       // OctalDigit OctalDigit
2982       // ZeroToThree OctalDigit OctalDigit
2983       int number = Character.getNumericValue(currentCharacter);
2984       if (number >= 0 && number <= 7) {
2985         boolean zeroToThreeNot = number > 3;
2986         if (Character.isDigit(currentCharacter = source[currentPosition++])) {
2987           int digit = Character.getNumericValue(currentCharacter);
2988           if (digit >= 0 && digit <= 7) {
2989             number = (number * 8) + digit;
2990             if (Character.isDigit(currentCharacter = source[currentPosition++])) {
2991               if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit
2992                 // Digit --> ignore last character
2993                 currentPosition--;
2994               } else {
2995                 digit = Character.getNumericValue(currentCharacter);
2996                 if (digit >= 0 && digit <= 7) {
2997                   // has read \ZeroToThree OctalDigit OctalDigit
2998                   number = (number * 8) + digit;
2999                 } else { // has read \ZeroToThree OctalDigit NonOctalDigit
3000                   // --> ignore last character
3001                   currentPosition--;
3002                 }
3003               }
3004             } else { // has read \OctalDigit NonDigit--> ignore last
3005               // character
3006               currentPosition--;
3007             }
3008           } else { // has read \OctalDigit NonOctalDigit--> ignore last
3009             // character
3010             currentPosition--;
3011           }
3012         } else { // has read \OctalDigit --> ignore last character
3013           currentPosition--;
3014         }
3015         if (number > 255)
3016           throw new InvalidInputException(INVALID_ESCAPE);
3017         currentCharacter = (char) number;
3018       }
3019     //else
3020     //     throw new InvalidInputException(INVALID_ESCAPE);
3021     }
3022   }
3023
3024   //  public int scanIdentifierOrKeyword() throws InvalidInputException {
3025   //    return scanIdentifierOrKeyword( false );
3026   //  }
3027   public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
3028     //test keywords
3029     //first dispatch on the first char.
3030     //then the length. If there are several
3031     //keywors with the same length AND the same first char, then do another
3032     //disptach on the second char :-)...cool....but fast !
3033     useAssertAsAnIndentifier = false;
3034     while (getNextCharAsJavaIdentifierPart()) {
3035     }
3036     ;
3037     if (isVariable) {
3038       //      if (new String(getCurrentTokenSource()).equals("$this")) {
3039       //        return TokenNamethis;
3040       //      }
3041       return TokenNameVariable;
3042     }
3043     int index, length;
3044     char[] data;
3045     char firstLetter;
3046     //    if (withoutUnicodePtr == 0)
3047     //quick test on length == 1 but not on length > 12 while most identifier
3048     //have a length which is <= 12...but there are lots of identifier with
3049     //only one char....
3050     //      {
3051     if ((length = currentPosition - startPosition) == 1)
3052       return TokenNameIdentifier;
3053     //  data = source;
3054     data = new char[length];
3055     index = startPosition;
3056     for (int i = 0; i < length; i++) {
3057       data[i] = Character.toLowerCase(source[index + i]);
3058     }
3059     index = 0;
3060     //    } else {
3061     //      if ((length = withoutUnicodePtr) == 1)
3062     //        return TokenNameIdentifier;
3063     //      // data = withoutUnicodeBuffer;
3064     //      data = new char[withoutUnicodeBuffer.length];
3065     //      for (int i = 0; i < withoutUnicodeBuffer.length; i++) {
3066     //        data[i] = Character.toLowerCase(withoutUnicodeBuffer[i]);
3067     //      }
3068     //      index = 1;
3069     //    }
3070     firstLetter = data[index];
3071     switch (firstLetter) {
3072     case '_':
3073       switch (length) {
3074       case 8:
3075         //__FILE__
3076         if ((data[++index] == '_') && (data[++index] == 'f') && (data[++index] == 'i') && (data[++index] == 'l')
3077             && (data[++index] == 'e') && (data[++index] == '_') && (data[++index] == '_'))
3078           return TokenNameFILE;
3079         index = 0; //__LINE__
3080         if ((data[++index] == '_') && (data[++index] == 'l') && (data[++index] == 'i') && (data[++index] == 'n')
3081             && (data[++index] == 'e') && (data[++index] == '_') && (data[++index] == '_'))
3082           return TokenNameLINE;
3083         break;
3084       case 9:
3085         //__CLASS__
3086         if ((data[++index] == '_') && (data[++index] == 'c') && (data[++index] == 'l') && (data[++index] == 'a')
3087             && (data[++index] == 's') && (data[++index] == 's') && (data[++index] == '_') && (data[++index] == '_'))
3088           return TokenNameCLASS_C;
3089         break;
3090       case 11:
3091         //__METHOD__
3092         if ((data[++index] == '_') && (data[++index] == 'm') && (data[++index] == 'e') && (data[++index] == 't')
3093             && (data[++index] == 'h') && (data[++index] == 'o') && (data[++index] == 'd') && (data[++index] == '_')
3094             && (data[++index] == '_'))
3095           return TokenNameMETHOD_C;
3096         break;
3097       case 12:
3098         //__FUNCTION__
3099         if ((data[++index] == '_') && (data[++index] == 'f') && (data[++index] == 'u') && (data[++index] == 'n')
3100             && (data[++index] == 'c') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'o')
3101             && (data[++index] == 'n') && (data[++index] == '_') && (data[++index] == '_'))
3102           return TokenNameFUNC_C;
3103         break;
3104       }
3105       return TokenNameIdentifier;
3106     case 'a':
3107       // as and array abstract
3108       switch (length) {
3109       case 2:
3110         //as
3111         if ((data[++index] == 's')) {
3112           return TokenNameas;
3113         } else {
3114           return TokenNameIdentifier;
3115         }
3116       case 3:
3117         //and
3118         if ((data[++index] == 'n') && (data[++index] == 'd')) {
3119           return TokenNameand;
3120         } else {
3121           return TokenNameIdentifier;
3122         }
3123       case 5:
3124         // array
3125         if ((data[++index] == 'r') && (data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'y'))
3126           return TokenNamearray;
3127         else
3128           return TokenNameIdentifier;
3129       case 8:
3130         if ((data[++index] == 'b') && (data[++index] == 's') && (data[++index] == 't') && (data[++index] == 'r')
3131             && (data[++index] == 'a') && (data[++index] == 'c') && (data[++index] == 't'))
3132           return TokenNameabstract;
3133         else
3134           return TokenNameIdentifier;
3135       default:
3136         return TokenNameIdentifier;
3137       }
3138     case 'b':
3139       //break
3140       switch (length) {
3141       case 5:
3142         if ((data[++index] == 'r') && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'k'))
3143           return TokenNamebreak;
3144         else
3145           return TokenNameIdentifier;
3146       default:
3147         return TokenNameIdentifier;
3148       }
3149     case 'c':
3150       //case catch class clone const continue
3151       switch (length) {
3152       case 4:
3153         if ((data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 'e'))
3154           return TokenNamecase;
3155         else
3156           return TokenNameIdentifier;
3157       case 5:
3158         if ((data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
3159           return TokenNamecatch;
3160         index = 0;
3161         if ((data[++index] == 'l') && (data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 's'))
3162           return TokenNameclass;
3163         index = 0;
3164         if ((data[++index] == 'l') && (data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 'e'))
3165           return TokenNameclone;
3166         index = 0;
3167         if ((data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 't'))
3168           return TokenNameconst;
3169         else
3170           return TokenNameIdentifier;
3171       case 8:
3172         if ((data[++index] == 'o') && (data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 'i')
3173             && (data[++index] == 'n') && (data[++index] == 'u') && (data[++index] == 'e'))
3174           return TokenNamecontinue;
3175         else
3176           return TokenNameIdentifier;
3177       default:
3178         return TokenNameIdentifier;
3179       }
3180     case 'd':
3181       // declare default do die
3182       // TODO delete define ==> no keyword !
3183       switch (length) {
3184       case 2:
3185         if ((data[++index] == 'o'))
3186           return TokenNamedo;
3187         else
3188           return TokenNameIdentifier;
3189       //          case 6 :
3190       //            if ((data[++index] == 'e')
3191       //              && (data[++index] == 'f')
3192       //              && (data[++index] == 'i')
3193       //              && (data[++index] == 'n')
3194       //              && (data[++index] == 'e'))
3195       //              return TokenNamedefine;
3196       //            else
3197       //              return TokenNameIdentifier;
3198       case 7:
3199         if ((data[++index] == 'e') && (data[++index] == 'c') && (data[++index] == 'l') && (data[++index] == 'a')
3200             && (data[++index] == 'r') && (data[++index] == 'e'))
3201           return TokenNamedeclare;
3202         index = 0;
3203         if ((data[++index] == 'e') && (data[++index] == 'f') && (data[++index] == 'a') && (data[++index] == 'u')
3204             && (data[++index] == 'l') && (data[++index] == 't'))
3205           return TokenNamedefault;
3206         else
3207           return TokenNameIdentifier;
3208       default:
3209         return TokenNameIdentifier;
3210       }
3211     case 'e':
3212       //echo else exit elseif extends eval
3213       switch (length) {
3214       case 4:
3215         if ((data[++index] == 'c') && (data[++index] == 'h') && (data[++index] == 'o'))
3216           return TokenNameecho;
3217         else if ((data[index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
3218           return TokenNameelse;
3219         else if ((data[index] == 'x') && (data[++index] == 'i') && (data[++index] == 't'))
3220           return TokenNameexit;
3221         else if ((data[index] == 'v') && (data[++index] == 'a') && (data[++index] == 'l'))
3222           return TokenNameeval;
3223         else
3224           return TokenNameIdentifier;
3225       case 5:
3226         // endif empty
3227         if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'i') && (data[++index] == 'f'))
3228           return TokenNameendif;
3229         if ((data[index] == 'm') && (data[++index] == 'p') && (data[++index] == 't') && (data[++index] == 'y'))
3230           return TokenNameempty;
3231         else
3232           return TokenNameIdentifier;
3233       case 6:
3234         // endfor
3235         if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'f') && (data[++index] == 'o')
3236             && (data[++index] == 'r'))
3237           return TokenNameendfor;
3238         else if ((data[index] == 'l') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 'i')
3239             && (data[++index] == 'f'))
3240           return TokenNameelseif;
3241         else
3242           return TokenNameIdentifier;
3243       case 7:
3244         if ((data[++index] == 'x') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'n')
3245             && (data[++index] == 'd') && (data[++index] == 's'))
3246           return TokenNameextends;
3247         else
3248           return TokenNameIdentifier;
3249       case 8:
3250         // endwhile
3251         if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'w') && (data[++index] == 'h')
3252             && (data[++index] == 'i') && (data[++index] == 'l') && (data[++index] == 'e'))
3253           return TokenNameendwhile;
3254         else
3255           return TokenNameIdentifier;
3256       case 9:
3257         // endswitch
3258         if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 's') && (data[++index] == 'w')
3259             && (data[++index] == 'i') && (data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
3260           return TokenNameendswitch;
3261         else
3262           return TokenNameIdentifier;
3263       case 10:
3264         // enddeclare
3265         if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'd') && (data[++index] == 'e')
3266             && (data[++index] == 'c') && (data[++index] == 'l') && (data[++index] == 'a') && (data[++index] == 'r')
3267             && (data[++index] == 'e'))
3268           return TokenNameenddeclare;
3269         index = 0;
3270         if ((data[++index] == 'n') // endforeach
3271             && (data[++index] == 'd') && (data[++index] == 'f') && (data[++index] == 'o') && (data[++index] == 'r')
3272             && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'c') && (data[++index] == 'h'))
3273           return TokenNameendforeach;
3274         else
3275           return TokenNameIdentifier;
3276       default:
3277         return TokenNameIdentifier;
3278       }
3279     case 'f':
3280       //for false final function
3281       switch (length) {
3282       case 3:
3283         if ((data[++index] == 'o') && (data[++index] == 'r'))
3284           return TokenNamefor;
3285         else
3286           return TokenNameIdentifier;
3287       case 5:
3288         //            if ((data[++index] == 'a') && (data[++index] == 'l')
3289         //                && (data[++index] == 's') && (data[++index] == 'e'))
3290         //              return TokenNamefalse;
3291         if ((data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 'a') && (data[++index] == 'l'))
3292           return TokenNamefinal;
3293         else
3294           return TokenNameIdentifier;
3295       case 7:
3296         // foreach
3297         if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 'e') && (data[++index] == 'a')
3298             && (data[++index] == 'c') && (data[++index] == 'h'))
3299           return TokenNameforeach;
3300         else
3301           return TokenNameIdentifier;
3302       case 8:
3303         // function
3304         if ((data[++index] == 'u') && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 't')
3305             && (data[++index] == 'i') && (data[++index] == 'o') && (data[++index] == 'n'))
3306           return TokenNamefunction;
3307         else
3308           return TokenNameIdentifier;
3309       default:
3310         return TokenNameIdentifier;
3311       }
3312     case 'g':
3313       //global
3314       if (length == 6) {
3315         if ((data[++index] == 'l') && (data[++index] == 'o') && (data[++index] == 'b') && (data[++index] == 'a')
3316             && (data[++index] == 'l')) {
3317           return TokenNameglobal;
3318         }
3319       }
3320       return TokenNameIdentifier;
3321     case 'i':
3322       //if int isset include include_once instanceof interface implements
3323       switch (length) {
3324       case 2:
3325         if (data[++index] == 'f')
3326           return TokenNameif;
3327         else
3328           return TokenNameIdentifier;
3329       //          case 3 :
3330       //            if ((data[++index] == 'n') && (data[++index] == 't'))
3331       //              return TokenNameint;
3332       //            else
3333       //              return TokenNameIdentifier;
3334       case 5:
3335         if ((data[++index] == 's') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 't'))
3336           return TokenNameisset;
3337         else
3338           return TokenNameIdentifier;
3339       case 7:
3340         if ((data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'l') && (data[++index] == 'u')
3341             && (data[++index] == 'd') && (data[++index] == 'e'))
3342           return TokenNameinclude;
3343         else
3344           return TokenNameIdentifier;
3345       case 9:
3346         // interface
3347         if ((data[++index] == 'n') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'r')
3348             && (data[++index] == 'f') && (data[++index] == 'a') && (data[++index] == 'c') && (data[++index] == 'e'))
3349           return TokenNameinterface;
3350         else
3351           return TokenNameIdentifier;
3352       case 10:
3353         // instanceof
3354         if ((data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 't') && (data[++index] == 'a')
3355             && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'e') && (data[++index] == 'o')
3356             && (data[++index] == 'f'))
3357           return TokenNameinstanceof;
3358         if ((data[index] == 'm') && (data[++index] == 'p') && (data[++index] == 'l') && (data[++index] == 'e')
3359             && (data[++index] == 'm') && (data[++index] == 'e') && (data[++index] == 'n') && (data[++index] == 't')
3360             && (data[++index] == 's'))
3361           return TokenNameimplements;
3362         else
3363           return TokenNameIdentifier;
3364       case 12:
3365         if ((data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'l') && (data[++index] == 'u')
3366             && (data[++index] == 'd') && (data[++index] == 'e') && (data[++index] == '_') && (data[++index] == 'o')
3367             && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'e'))
3368           return TokenNameinclude_once;
3369         else
3370           return TokenNameIdentifier;
3371       default:
3372         return TokenNameIdentifier;
3373       }
3374     case 'l':
3375       //list
3376       if (length == 4) {
3377         if ((data[++index] == 'i') && (data[++index] == 's') && (data[++index] == 't')) {
3378           return TokenNamelist;
3379         }
3380       }
3381       return TokenNameIdentifier;
3382     case 'n':
3383       // new null
3384       switch (length) {
3385       case 3:
3386         if ((data[++index] == 'e') && (data[++index] == 'w'))
3387           return TokenNamenew;
3388         else
3389           return TokenNameIdentifier;
3390       //          case 4 :
3391       //            if ((data[++index] == 'u') && (data[++index] == 'l')
3392       //                && (data[++index] == 'l'))
3393       //              return TokenNamenull;
3394       //            else
3395       //              return TokenNameIdentifier;
3396       default:
3397         return TokenNameIdentifier;
3398       }
3399     case 'o':
3400       // or old_function
3401       if (length == 2) {
3402         if (data[++index] == 'r') {
3403           return TokenNameor;
3404         }
3405       }
3406       //        if (length == 12) {
3407       //          if ((data[++index] == 'l')
3408       //            && (data[++index] == 'd')
3409       //            && (data[++index] == '_')
3410       //            && (data[++index] == 'f')
3411       //            && (data[++index] == 'u')
3412       //            && (data[++index] == 'n')
3413       //            && (data[++index] == 'c')
3414       //            && (data[++index] == 't')
3415       //            && (data[++index] == 'i')
3416       //            && (data[++index] == 'o')
3417       //            && (data[++index] == 'n')) {
3418       //            return TokenNameold_function;
3419       //          }
3420       //        }
3421       return TokenNameIdentifier;
3422     case 'p':
3423       // print public private protected
3424       switch (length) {
3425       case 5:
3426         if ((data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 't')) {
3427           return TokenNameprint;
3428         } else
3429           return TokenNameIdentifier;
3430       case 6:
3431         if ((data[++index] == 'u') && (data[++index] == 'b') && (data[++index] == 'l') && (data[++index] == 'i')
3432             && (data[++index] == 'c')) {
3433           return TokenNamepublic;
3434         } else
3435           return TokenNameIdentifier;
3436       case 7:
3437         if ((data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'v') && (data[++index] == 'a')
3438             && (data[++index] == 't') && (data[++index] == 'e')) {
3439           return TokenNameprivate;
3440         } else
3441           return TokenNameIdentifier;
3442       case 9:
3443         if ((data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 't') && (data[++index] == 'e')
3444             && (data[++index] == 'c') && (data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'd')) {
3445           return TokenNameprotected;
3446         } else
3447           return TokenNameIdentifier;
3448       }
3449       return TokenNameIdentifier;
3450     case 'r':
3451       //return require require_once
3452       if (length == 6) {
3453         if ((data[++index] == 'e') && (data[++index] == 't') && (data[++index] == 'u') && (data[++index] == 'r')
3454             && (data[++index] == 'n')) {
3455           return TokenNamereturn;
3456         }
3457       } else if (length == 7) {
3458         if ((data[++index] == 'e') && (data[++index] == 'q') && (data[++index] == 'u') && (data[++index] == 'i')
3459             && (data[++index] == 'r') && (data[++index] == 'e')) {
3460           return TokenNamerequire;
3461         }
3462       } else if (length == 12) {
3463         if ((data[++index] == 'e') && (data[++index] == 'q') && (data[++index] == 'u') && (data[++index] == 'i')
3464             && (data[++index] == 'r') && (data[++index] == 'e') && (data[++index] == '_') && (data[++index] == 'o')
3465             && (data[++index] == 'n') && (data[++index] == 'c') && (data[++index] == 'e')) {
3466           return TokenNamerequire_once;
3467         }
3468       } else
3469         return TokenNameIdentifier;
3470     case 's':
3471       //static switch
3472       switch (length) {
3473       case 6:
3474         if (data[++index] == 't')
3475           if ((data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'i') && (data[++index] == 'c')) {
3476             return TokenNamestatic;
3477           } else
3478             return TokenNameIdentifier;
3479         else if ((data[index] == 'w') && (data[++index] == 'i') && (data[++index] == 't') && (data[++index] == 'c')
3480             && (data[++index] == 'h'))
3481           return TokenNameswitch;
3482         else
3483           return TokenNameIdentifier;
3484       default:
3485         return TokenNameIdentifier;
3486       }
3487     case 't':
3488       // try true throw
3489       switch (length) {
3490       case 3:
3491         if ((data[++index] == 'r') && (data[++index] == 'y'))
3492           return TokenNametry;
3493         else
3494           return TokenNameIdentifier;
3495       //          case 4 :
3496       //            if ((data[++index] == 'r') && (data[++index] == 'u')
3497       //                && (data[++index] == 'e'))
3498       //              return TokenNametrue;
3499       //            else
3500       //              return TokenNameIdentifier;
3501       case 5:
3502         if ((data[++index] == 'h') && (data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 'w'))
3503           return TokenNamethrow;
3504         else
3505           return TokenNameIdentifier;
3506       default:
3507         return TokenNameIdentifier;
3508       }
3509     case 'u':
3510       //use unset
3511       switch (length) {
3512       case 3:
3513         if ((data[++index] == 's') && (data[++index] == 'e'))
3514           return TokenNameuse;
3515         else
3516           return TokenNameIdentifier;
3517       case 5:
3518         if ((data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 't'))
3519           return TokenNameunset;
3520         else
3521           return TokenNameIdentifier;
3522       default:
3523         return TokenNameIdentifier;
3524       }
3525     case 'v':
3526       //var
3527       switch (length) {
3528       case 3:
3529         if ((data[++index] == 'a') && (data[++index] == 'r'))
3530           return TokenNamevar;
3531         else
3532           return TokenNameIdentifier;
3533       default:
3534         return TokenNameIdentifier;
3535       }
3536     case 'w':
3537       //while
3538       switch (length) {
3539       case 5:
3540         if ((data[++index] == 'h') && (data[++index] == 'i') && (data[++index] == 'l') && (data[++index] == 'e'))
3541           return TokenNamewhile;
3542         else
3543           return TokenNameIdentifier;
3544       //case 6:if ( (data[++index] =='i') && (data[++index]=='d') &&
3545       // (data[++index]=='e') && (data[++index]=='f')&&
3546       // (data[++index]=='p'))
3547       //return TokenNamewidefp ;
3548       //else
3549       //return TokenNameIdentifier;
3550       default:
3551         return TokenNameIdentifier;
3552       }
3553     case 'x':
3554       //xor
3555       switch (length) {
3556       case 3:
3557         if ((data[++index] == 'o') && (data[++index] == 'r'))
3558           return TokenNamexor;
3559         else
3560           return TokenNameIdentifier;
3561       default:
3562         return TokenNameIdentifier;
3563       }
3564     default:
3565       return TokenNameIdentifier;
3566     }
3567   }
3568
3569   public int scanNumber(boolean dotPrefix) throws InvalidInputException {
3570     //when entering this method the currentCharacter is the firt
3571     //digit of the number , i.e. it may be preceeded by a . when
3572     //dotPrefix is true
3573     boolean floating = dotPrefix;
3574     if ((!dotPrefix) && (currentCharacter == '0')) {
3575       if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
3576         //force the first char of the hexa number do exist...
3577         // consume next character
3578         unicodeAsBackSlash = false;
3579         currentCharacter = source[currentPosition++];
3580         //        if (((currentCharacter = source[currentPosition++]) == '\\')
3581         //          && (source[currentPosition] == 'u')) {
3582         //          getNextUnicodeChar();
3583         //        } else {
3584         //          if (withoutUnicodePtr != 0) {
3585         //            withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3586         //          }
3587         //        }
3588         if (Character.digit(currentCharacter, 16) == -1)
3589           throw new InvalidInputException(INVALID_HEXA);
3590         //---end forcing--
3591         while (getNextCharAsDigit(16)) {
3592         }
3593         ;
3594         //        if (getNextChar('l', 'L') >= 0)
3595         //          return TokenNameLongLiteral;
3596         //        else
3597         return TokenNameIntegerLiteral;
3598       }
3599       //there is x or X in the number
3600       //potential octal ! ... some one may write 000099.0 ! thus 00100 <
3601       // 00078.0 is true !!!!! crazy language
3602       if (getNextCharAsDigit()) {
3603         //-------------potential octal-----------------
3604         while (getNextCharAsDigit()) {
3605         }
3606         ;
3607         //        if (getNextChar('l', 'L') >= 0) {
3608         //          return TokenNameLongLiteral;
3609         //        }
3610         //
3611         //        if (getNextChar('f', 'F') >= 0) {
3612         //          return TokenNameFloatingPointLiteral;
3613         //        }
3614         if (getNextChar('d', 'D') >= 0) {
3615           return TokenNameDoubleLiteral;
3616         } else { //make the distinction between octal and float ....
3617           if (getNextChar('.')) { //bingo ! ....
3618             while (getNextCharAsDigit()) {
3619             }
3620             ;
3621             if (getNextChar('e', 'E') >= 0) {
3622               // consume next character
3623               unicodeAsBackSlash = false;
3624               currentCharacter = source[currentPosition++];
3625               //              if (((currentCharacter = source[currentPosition++]) == '\\')
3626               //                && (source[currentPosition] == 'u')) {
3627               //                getNextUnicodeChar();
3628               //              } else {
3629               //                if (withoutUnicodePtr != 0) {
3630               //                  withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3631               //                }
3632               //              }
3633               if ((currentCharacter == '-') || (currentCharacter == '+')) {
3634                 // consume next character
3635                 unicodeAsBackSlash = false;
3636                 currentCharacter = source[currentPosition++];
3637                 //                if (((currentCharacter = source[currentPosition++]) == '\\')
3638                 //                  && (source[currentPosition] == 'u')) {
3639                 //                  getNextUnicodeChar();
3640                 //                } else {
3641                 //                  if (withoutUnicodePtr != 0) {
3642                 //                    withoutUnicodeBuffer[++withoutUnicodePtr] =
3643                 //                      currentCharacter;
3644                 //                  }
3645                 //                }
3646               }
3647               if (!Character.isDigit(currentCharacter))
3648                 throw new InvalidInputException(INVALID_FLOAT);
3649               while (getNextCharAsDigit()) {
3650               }
3651               ;
3652             }
3653             //            if (getNextChar('f', 'F') >= 0)
3654             //              return TokenNameFloatingPointLiteral;
3655             getNextChar('d', 'D'); //jump over potential d or D
3656             return TokenNameDoubleLiteral;
3657           } else {
3658             return TokenNameIntegerLiteral;
3659           }
3660         }
3661       } else {
3662         /* carry on */
3663       }
3664     }
3665     while (getNextCharAsDigit()) {
3666     }
3667     ;
3668     //    if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
3669     //      return TokenNameLongLiteral;
3670     if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
3671       while (getNextCharAsDigit()) {
3672       }
3673       ;
3674       floating = true;
3675     }
3676     //if floating is true both exponant and suffix may be optional
3677     if (getNextChar('e', 'E') >= 0) {
3678       floating = true;
3679       // consume next character
3680       unicodeAsBackSlash = false;
3681       currentCharacter = source[currentPosition++];
3682       //      if (((currentCharacter = source[currentPosition++]) == '\\')
3683       //        && (source[currentPosition] == 'u')) {
3684       //        getNextUnicodeChar();
3685       //      } else {
3686       //        if (withoutUnicodePtr != 0) {
3687       //          withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3688       //        }
3689       //      }
3690       if ((currentCharacter == '-') || (currentCharacter == '+')) { // consume
3691         // next
3692         // character
3693         unicodeAsBackSlash = false;
3694         currentCharacter = source[currentPosition++];
3695         //        if (((currentCharacter = source[currentPosition++]) == '\\')
3696         //          && (source[currentPosition] == 'u')) {
3697         //          getNextUnicodeChar();
3698         //        } else {
3699         //          if (withoutUnicodePtr != 0) {
3700         //            withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3701         //          }
3702         //        }
3703       }
3704       if (!Character.isDigit(currentCharacter))
3705         throw new InvalidInputException(INVALID_FLOAT);
3706       while (getNextCharAsDigit()) {
3707       }
3708       ;
3709     }
3710     if (getNextChar('d', 'D') >= 0)
3711       return TokenNameDoubleLiteral;
3712     //    if (getNextChar('f', 'F') >= 0)
3713     //      return TokenNameFloatingPointLiteral;
3714     //the long flag has been tested before
3715     return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
3716   }
3717
3718   /**
3719    * Search the line number corresponding to a specific position
3720    *  
3721    */
3722   public final int getLineNumber(int position) {
3723     if (lineEnds == null)
3724       return 1;
3725     int length = linePtr + 1;
3726     if (length == 0)
3727       return 1;
3728     int g = 0, d = length - 1;
3729     int m = 0;
3730     while (g <= d) {
3731       m = (g + d) / 2;
3732       if (position < lineEnds[m]) {
3733         d = m - 1;
3734       } else if (position > lineEnds[m]) {
3735         g = m + 1;
3736       } else {
3737         return m + 1;
3738       }
3739     }
3740     if (position < lineEnds[m]) {
3741       return m + 1;
3742     }
3743     return m + 2;
3744   }
3745
3746   public void setPHPMode(boolean mode) {
3747     phpMode = mode;
3748   }
3749
3750   public final void setSource(char[] source) {
3751     setSource(null, source);
3752   }
3753
3754   public final void setSource(ICompilationUnit compilationUnit, char[] source) {
3755     //the source-buffer is set to sourceString
3756     this.compilationUnit = compilationUnit;
3757     if (source == null) {
3758       this.source = new char[0];
3759     } else {
3760       this.source = source;
3761     }
3762     startPosition = -1;
3763     initialPosition = currentPosition = 0;
3764     containsAssertKeyword = false;
3765     withoutUnicodeBuffer = new char[this.source.length];
3766     encapsedStringStack = new Stack();
3767   }
3768
3769   public String toString() {
3770     if (startPosition == source.length)
3771       return "EOF\n\n" + new String(source); //$NON-NLS-1$
3772     if (currentPosition > source.length)
3773       return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
3774     char front[] = new char[startPosition];
3775     System.arraycopy(source, 0, front, 0, startPosition);
3776     int middleLength = (currentPosition - 1) - startPosition + 1;
3777     char middle[];
3778     if (middleLength > -1) {
3779       middle = new char[middleLength];
3780       System.arraycopy(source, startPosition, middle, 0, middleLength);
3781     } else {
3782       middle = new char[0];
3783     }
3784     char end[] = new char[source.length - (currentPosition - 1)];
3785     System.arraycopy(source, (currentPosition - 1) + 1, end, 0, source.length - (currentPosition - 1) - 1);
3786     return new String(front) + "\n===============================\nStarts here -->" //$NON-NLS-1$
3787         + new String(middle) + "<-- Ends here\n===============================\n" //$NON-NLS-1$
3788         + new String(end);
3789   }
3790
3791   public final String toStringAction(int act) {
3792     switch (act) {
3793     case TokenNameERROR:
3794       return "ScannerError"; // + new String(getCurrentTokenSource()) + ")";
3795     // //$NON-NLS-1$
3796     case TokenNameINLINE_HTML:
3797       return "Inline-HTML(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3798     case TokenNameIdentifier:
3799       return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3800     case TokenNameVariable:
3801       return "Variable(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3802     case TokenNameabstract:
3803       return "abstract"; //$NON-NLS-1$
3804     case TokenNameand:
3805       return "AND"; //$NON-NLS-1$
3806     case TokenNamearray:
3807       return "array"; //$NON-NLS-1$
3808     case TokenNameas:
3809       return "as"; //$NON-NLS-1$
3810     case TokenNamebreak:
3811       return "break"; //$NON-NLS-1$
3812     case TokenNamecase:
3813       return "case"; //$NON-NLS-1$
3814     case TokenNameclass:
3815       return "class"; //$NON-NLS-1$
3816     case TokenNamecatch:
3817       return "catch"; //$NON-NLS-1$
3818     case TokenNameclone:
3819       //$NON-NLS-1$
3820       return "clone";
3821     case TokenNameconst:
3822       //$NON-NLS-1$
3823       return "const";
3824     case TokenNamecontinue:
3825       return "continue"; //$NON-NLS-1$
3826     case TokenNamedefault:
3827       return "default"; //$NON-NLS-1$
3828     //      case TokenNamedefine :
3829     //        return "define"; //$NON-NLS-1$
3830     case TokenNamedo:
3831       return "do"; //$NON-NLS-1$
3832     case TokenNameecho:
3833       return "echo"; //$NON-NLS-1$
3834     case TokenNameelse:
3835       return "else"; //$NON-NLS-1$
3836     case TokenNameelseif:
3837       return "elseif"; //$NON-NLS-1$
3838     case TokenNameendfor:
3839       return "endfor"; //$NON-NLS-1$
3840     case TokenNameendforeach:
3841       return "endforeach"; //$NON-NLS-1$
3842     case TokenNameendif:
3843       return "endif"; //$NON-NLS-1$
3844     case TokenNameendswitch:
3845       return "endswitch"; //$NON-NLS-1$
3846     case TokenNameendwhile:
3847       return "endwhile"; //$NON-NLS-1$
3848     case TokenNameexit:
3849       return "exit";
3850     case TokenNameextends:
3851       return "extends"; //$NON-NLS-1$
3852     //      case TokenNamefalse :
3853     //        return "false"; //$NON-NLS-1$
3854     case TokenNamefinal:
3855       return "final"; //$NON-NLS-1$
3856     case TokenNamefor:
3857       return "for"; //$NON-NLS-1$
3858     case TokenNameforeach:
3859       return "foreach"; //$NON-NLS-1$
3860     case TokenNamefunction:
3861       return "function"; //$NON-NLS-1$
3862     case TokenNameglobal:
3863       return "global"; //$NON-NLS-1$
3864     case TokenNameif:
3865       return "if"; //$NON-NLS-1$
3866     case TokenNameimplements:
3867       return "implements"; //$NON-NLS-1$
3868     case TokenNameinclude:
3869       return "include"; //$NON-NLS-1$
3870     case TokenNameinclude_once:
3871       return "include_once"; //$NON-NLS-1$
3872     case TokenNameinstanceof:
3873       return "instanceof"; //$NON-NLS-1$
3874     case TokenNameinterface:
3875       return "interface"; //$NON-NLS-1$
3876     case TokenNameisset:
3877       return "isset"; //$NON-NLS-1$
3878     case TokenNamelist:
3879       return "list"; //$NON-NLS-1$
3880     case TokenNamenew:
3881       return "new"; //$NON-NLS-1$
3882     //      case TokenNamenull :
3883     //        return "null"; //$NON-NLS-1$
3884     case TokenNameor:
3885       return "OR"; //$NON-NLS-1$
3886     case TokenNameprint:
3887       return "print"; //$NON-NLS-1$
3888     case TokenNameprivate:
3889       return "private"; //$NON-NLS-1$
3890     case TokenNameprotected:
3891       return "protected"; //$NON-NLS-1$
3892     case TokenNamepublic:
3893       return "public"; //$NON-NLS-1$
3894     case TokenNamerequire:
3895       return "require"; //$NON-NLS-1$
3896     case TokenNamerequire_once:
3897       return "require_once"; //$NON-NLS-1$
3898     case TokenNamereturn:
3899       return "return"; //$NON-NLS-1$
3900     case TokenNamestatic:
3901       return "static"; //$NON-NLS-1$
3902     case TokenNameswitch:
3903       return "switch"; //$NON-NLS-1$
3904     //      case TokenNametrue :
3905     //        return "true"; //$NON-NLS-1$
3906     case TokenNameunset:
3907       return "unset"; //$NON-NLS-1$
3908     case TokenNamevar:
3909       return "var"; //$NON-NLS-1$
3910     case TokenNamewhile:
3911       return "while"; //$NON-NLS-1$
3912     case TokenNamexor:
3913       return "XOR"; //$NON-NLS-1$
3914     //      case TokenNamethis :
3915     //        return "$this"; //$NON-NLS-1$
3916     case TokenNameIntegerLiteral:
3917       return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3918     case TokenNameDoubleLiteral:
3919       return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3920     case TokenNameStringDoubleQuote:
3921       return "StringLiteral(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3922     case TokenNameStringSingleQuote:
3923       return "StringConstant(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3924     case TokenNameStringInterpolated:
3925       return "StringInterpolated(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3926     case TokenNameEncapsedString0:
3927       return "`"; //$NON-NLS-1$  
3928     case TokenNameEncapsedString1:
3929       return "\'"; //$NON-NLS-1$  
3930     case TokenNameEncapsedString2:
3931       return "\""; //$NON-NLS-1$  
3932     case TokenNameSTRING:
3933       return "STRING(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3934     case TokenNameHEREDOC:
3935       return "HEREDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3936     case TokenNamePLUS_PLUS:
3937       return "++"; //$NON-NLS-1$
3938     case TokenNameMINUS_MINUS:
3939       return "--"; //$NON-NLS-1$
3940     case TokenNameEQUAL_EQUAL:
3941       return "=="; //$NON-NLS-1$
3942     case TokenNameEQUAL_EQUAL_EQUAL:
3943       return "==="; //$NON-NLS-1$
3944     case TokenNameEQUAL_GREATER:
3945       return "=>"; //$NON-NLS-1$
3946     case TokenNameLESS_EQUAL:
3947       return "<="; //$NON-NLS-1$
3948     case TokenNameGREATER_EQUAL:
3949       return ">="; //$NON-NLS-1$
3950     case TokenNameNOT_EQUAL:
3951       return "!="; //$NON-NLS-1$
3952     case TokenNameNOT_EQUAL_EQUAL:
3953       return "!=="; //$NON-NLS-1$
3954     case TokenNameLEFT_SHIFT:
3955       return "<<"; //$NON-NLS-1$
3956     case TokenNameRIGHT_SHIFT:
3957       return ">>"; //$NON-NLS-1$
3958     case TokenNamePLUS_EQUAL:
3959       return "+="; //$NON-NLS-1$
3960     case TokenNameMINUS_EQUAL:
3961       return "-="; //$NON-NLS-1$
3962     case TokenNameMULTIPLY_EQUAL:
3963       return "*="; //$NON-NLS-1$
3964     case TokenNameDIVIDE_EQUAL:
3965       return "/="; //$NON-NLS-1$
3966     case TokenNameAND_EQUAL:
3967       return "&="; //$NON-NLS-1$
3968     case TokenNameOR_EQUAL:
3969       return "|="; //$NON-NLS-1$
3970     case TokenNameXOR_EQUAL:
3971       return "^="; //$NON-NLS-1$
3972     case TokenNameREMAINDER_EQUAL:
3973       return "%="; //$NON-NLS-1$
3974     case TokenNameDOT_EQUAL:
3975       return ".="; //$NON-NLS-1$
3976     case TokenNameLEFT_SHIFT_EQUAL:
3977       return "<<="; //$NON-NLS-1$
3978     case TokenNameRIGHT_SHIFT_EQUAL:
3979       return ">>="; //$NON-NLS-1$
3980     case TokenNameOR_OR:
3981       return "||"; //$NON-NLS-1$
3982     case TokenNameAND_AND:
3983       return "&&"; //$NON-NLS-1$
3984     case TokenNamePLUS:
3985       return "+"; //$NON-NLS-1$
3986     case TokenNameMINUS:
3987       return "-"; //$NON-NLS-1$
3988     case TokenNameMINUS_GREATER:
3989       return "->";
3990     case TokenNameNOT:
3991       return "!"; //$NON-NLS-1$
3992     case TokenNameREMAINDER:
3993       return "%"; //$NON-NLS-1$
3994     case TokenNameXOR:
3995       return "^"; //$NON-NLS-1$
3996     case TokenNameAND:
3997       return "&"; //$NON-NLS-1$
3998     case TokenNameMULTIPLY:
3999       return "*"; //$NON-NLS-1$
4000     case TokenNameOR:
4001       return "|"; //$NON-NLS-1$
4002     case TokenNameTWIDDLE:
4003       return "~"; //$NON-NLS-1$
4004     case TokenNameTWIDDLE_EQUAL:
4005       return "~="; //$NON-NLS-1$
4006     case TokenNameDIVIDE:
4007       return "/"; //$NON-NLS-1$
4008     case TokenNameGREATER:
4009       return ">"; //$NON-NLS-1$
4010     case TokenNameLESS:
4011       return "<"; //$NON-NLS-1$
4012     case TokenNameLPAREN:
4013       return "("; //$NON-NLS-1$
4014     case TokenNameRPAREN:
4015       return ")"; //$NON-NLS-1$
4016     case TokenNameLBRACE:
4017       return "{"; //$NON-NLS-1$
4018     case TokenNameRBRACE:
4019       return "}"; //$NON-NLS-1$
4020     case TokenNameLBRACKET:
4021       return "["; //$NON-NLS-1$
4022     case TokenNameRBRACKET:
4023       return "]"; //$NON-NLS-1$
4024     case TokenNameSEMICOLON:
4025       return ";"; //$NON-NLS-1$
4026     case TokenNameQUESTION:
4027       return "?"; //$NON-NLS-1$
4028     case TokenNameCOLON:
4029       return ":"; //$NON-NLS-1$
4030     case TokenNameCOMMA:
4031       return ","; //$NON-NLS-1$
4032     case TokenNameDOT:
4033       return "."; //$NON-NLS-1$
4034     case TokenNameEQUAL:
4035       return "="; //$NON-NLS-1$
4036     case TokenNameAT:
4037       return "@";
4038     case TokenNameDOLLAR:
4039       return "$";
4040     case TokenNameDOLLAR_LBRACE:
4041       return "${";
4042     case TokenNameLBRACE_DOLLAR:
4043       return "{$";
4044     case TokenNameEOF:
4045       return "EOF"; //$NON-NLS-1$
4046     case TokenNameWHITESPACE:
4047       return "WHITESPACE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
4048     case TokenNameCOMMENT_LINE:
4049       return "COMMENT_LINE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
4050     case TokenNameCOMMENT_BLOCK:
4051       return "COMMENT_BLOCK(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
4052     case TokenNameCOMMENT_PHPDOC:
4053       return "COMMENT_PHPDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
4054     //      case TokenNameHTML :
4055     //        return "HTML(" + new String(getCurrentTokenSource()) + ")";
4056     // //$NON-NLS-1$
4057     case TokenNameFILE:
4058       return "__FILE__"; //$NON-NLS-1$
4059     case TokenNameLINE:
4060       return "__LINE__"; //$NON-NLS-1$
4061     case TokenNameCLASS_C:
4062       return "__CLASS__"; //$NON-NLS-1$
4063     case TokenNameMETHOD_C:
4064       return "__METHOD__"; //$NON-NLS-1$
4065     case TokenNameFUNC_C:
4066       return "__FUNCTION__"; //$NON-NLS-1
4067     case TokenNameboolCAST:
4068       return "( bool )"; //$NON-NLS-1$
4069     case TokenNameintCAST:
4070       return "( int )"; //$NON-NLS-1$
4071     case TokenNamedoubleCAST:
4072       return "( double )"; //$NON-NLS-1$
4073     case TokenNameobjectCAST:
4074       return "( object )"; //$NON-NLS-1$
4075     case TokenNamestringCAST:
4076       return "( string )"; //$NON-NLS-1$
4077     default:
4078       return "not-a-token(" + (new Integer(act)) + ") " + new String(getCurrentTokenSource()); //$NON-NLS-1$
4079     }
4080   }
4081
4082   public Scanner() {
4083     this(false, false);
4084   }
4085
4086   public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace) {
4087     this(tokenizeComments, tokenizeWhiteSpace, false);
4088   }
4089
4090   public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals) {
4091     this(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, false);
4092   }
4093
4094   public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals,
4095       boolean assertMode) {
4096     this(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, assertMode, false, null, null, true);
4097   }
4098
4099   public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals,
4100       boolean assertMode, boolean tokenizeStrings, char[][] taskTags, char[][] taskPriorities, boolean isTaskCaseSensitive) {
4101     this.eofPosition = Integer.MAX_VALUE;
4102     this.tokenizeComments = tokenizeComments;
4103     this.tokenizeWhiteSpace = tokenizeWhiteSpace;
4104     this.tokenizeStrings = tokenizeStrings;
4105     this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
4106     this.assertMode = assertMode;
4107     this.encapsedStringStack = null;
4108     this.taskTags = taskTags;
4109     this.taskPriorities = taskPriorities;
4110   }
4111
4112   private void checkNonExternalizeString() throws InvalidInputException {
4113     if (currentLine == null)
4114       return;
4115     parseTags(currentLine);
4116   }
4117
4118   private void parseTags(NLSLine line) throws InvalidInputException {
4119     String s = new String(getCurrentTokenSource());
4120     int pos = s.indexOf(TAG_PREFIX);
4121     int lineLength = line.size();
4122     while (pos != -1) {
4123       int start = pos + TAG_PREFIX_LENGTH;
4124       int end = s.indexOf(TAG_POSTFIX, start);
4125       String index = s.substring(start, end);
4126       int i = 0;
4127       try {
4128         i = Integer.parseInt(index) - 1;
4129         // Tags are one based not zero based.
4130       } catch (NumberFormatException e) {
4131         i = -1; // we don't want to consider this as a valid NLS tag
4132       }
4133       if (line.exists(i)) {
4134         line.set(i, null);
4135       }
4136       pos = s.indexOf(TAG_PREFIX, start);
4137     }
4138     this.nonNLSStrings = new StringLiteral[lineLength];
4139     int nonNLSCounter = 0;
4140     for (Iterator iterator = line.iterator(); iterator.hasNext();) {
4141       StringLiteral literal = (StringLiteral) iterator.next();
4142       if (literal != null) {
4143         this.nonNLSStrings[nonNLSCounter++] = literal;
4144       }
4145     }
4146     if (nonNLSCounter == 0) {
4147       this.nonNLSStrings = null;
4148       currentLine = null;
4149       return;
4150     }
4151     this.wasNonExternalizedStringLiteral = true;
4152     if (nonNLSCounter != lineLength) {
4153       System.arraycopy(this.nonNLSStrings, 0, (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0, nonNLSCounter);
4154     }
4155     currentLine = null;
4156   }
4157
4158   public final void scanEscapeCharacter() throws InvalidInputException {
4159     // the string with "\\u" is a legal string of two chars \ and u
4160     //thus we use a direct access to the source (for regular cases).
4161     if (unicodeAsBackSlash) {
4162       // consume next character
4163       unicodeAsBackSlash = false;
4164       //                        if (((currentCharacter = source[currentPosition++]) == '\\') &&
4165       // (source[currentPosition] == 'u')) {
4166       //                                getNextUnicodeChar();
4167       //                        } else {
4168       if (withoutUnicodePtr != 0) {
4169         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
4170         //                              }
4171       }
4172     } else
4173       currentCharacter = source[currentPosition++];
4174     switch (currentCharacter) {
4175     case 'b':
4176       currentCharacter = '\b';
4177       break;
4178     case 't':
4179       currentCharacter = '\t';
4180       break;
4181     case 'n':
4182       currentCharacter = '\n';
4183       break;
4184     case 'f':
4185       currentCharacter = '\f';
4186       break;
4187     case 'r':
4188       currentCharacter = '\r';
4189       break;
4190     case '\"':
4191       currentCharacter = '\"';
4192       break;
4193     case '\'':
4194       currentCharacter = '\'';
4195       break;
4196     case '\\':
4197       currentCharacter = '\\';
4198       break;
4199     default:
4200       // -----------octal escape--------------
4201       // OctalDigit
4202       // OctalDigit OctalDigit
4203       // ZeroToThree OctalDigit OctalDigit
4204       int number = Character.getNumericValue(currentCharacter);
4205       if (number >= 0 && number <= 7) {
4206         boolean zeroToThreeNot = number > 3;
4207         if (Character.isDigit(currentCharacter = source[currentPosition++])) {
4208           int digit = Character.getNumericValue(currentCharacter);
4209           if (digit >= 0 && digit <= 7) {
4210             number = (number * 8) + digit;
4211             if (Character.isDigit(currentCharacter = source[currentPosition++])) {
4212               if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit
4213                 // Digit --> ignore last character
4214                 currentPosition--;
4215               } else {
4216                 digit = Character.getNumericValue(currentCharacter);
4217                 if (digit >= 0 && digit <= 7) { // has read \ZeroToThree
4218                   // OctalDigit OctalDigit
4219                   number = (number * 8) + digit;
4220                 } else { // has read \ZeroToThree OctalDigit NonOctalDigit
4221                   // --> ignore last character
4222                   currentPosition--;
4223                 }
4224               }
4225             } else { // has read \OctalDigit NonDigit--> ignore last
4226               // character
4227               currentPosition--;
4228             }
4229           } else { // has read \OctalDigit NonOctalDigit--> ignore last
4230             // character
4231             currentPosition--;
4232           }
4233         } else { // has read \OctalDigit --> ignore last character
4234           currentPosition--;
4235         }
4236         if (number > 255)
4237           throw new InvalidInputException(INVALID_ESCAPE);
4238         currentCharacter = (char) number;
4239       } else
4240         throw new InvalidInputException(INVALID_ESCAPE);
4241     }
4242   }
4243
4244   //chech presence of task: tags
4245   //TODO (frederic) see if we need to take unicode characters into account...
4246   public void checkTaskTag(int commentStart, int commentEnd) {
4247     char[] src = this.source;
4248
4249     // only look for newer task: tags
4250     if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
4251       return;
4252     }
4253     int foundTaskIndex = this.foundTaskCount;
4254     char previous = src[commentStart + 1]; // should be '*' or '/'
4255     nextChar: for (int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) {
4256       char[] tag = null;
4257       char[] priority = null;
4258       // check for tag occurrence only if not ambiguous with javadoc tag
4259       if (previous != '@') {
4260         nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) {
4261           tag = this.taskTags[itag];
4262           int tagLength = tag.length;
4263           if (tagLength == 0)
4264             continue nextTag;
4265
4266           // ensure tag is not leaded with letter if tag starts with a letter
4267           if (Scanner.isPHPIdentifierStart(tag[0])) {
4268             if (Scanner.isPHPIdentifierPart(previous)) {
4269               continue nextTag;
4270             }
4271           }
4272
4273           for (int t = 0; t < tagLength; t++) {
4274             char sc, tc;
4275             int x = i + t;
4276             if (x >= this.eofPosition || x >= commentEnd)
4277               continue nextTag;
4278             if ((sc = src[i + t]) != (tc = tag[t])) { // case sensitive check
4279               if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) { // case insensitive check
4280                 continue nextTag;
4281               }
4282             }
4283           }
4284           // ensure tag is not followed with letter if tag finishes with a letter
4285           if (i + tagLength < commentEnd && Scanner.isPHPIdentifierPart(src[i + tagLength - 1])) {
4286             if (Scanner.isPHPIdentifierPart(src[i + tagLength]))
4287               continue nextTag;
4288           }
4289           if (this.foundTaskTags == null) {
4290             this.foundTaskTags = new char[5][];
4291             this.foundTaskMessages = new char[5][];
4292             this.foundTaskPriorities = new char[5][];
4293             this.foundTaskPositions = new int[5][];
4294           } else if (this.foundTaskCount == this.foundTaskTags.length) {
4295             System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0,
4296                 this.foundTaskCount);
4297             System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0,
4298                 this.foundTaskCount);
4299             System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0,
4300                 this.foundTaskCount);
4301             System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0,
4302                 this.foundTaskCount);
4303           }
4304
4305           priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null;
4306
4307           this.foundTaskTags[this.foundTaskCount] = tag;
4308           this.foundTaskPriorities[this.foundTaskCount] = priority;
4309           this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
4310           this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
4311           this.foundTaskCount++;
4312           i += tagLength - 1; // will be incremented when looping
4313           break nextTag;
4314         }
4315       }
4316       previous = src[i];
4317     }
4318     for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
4319       // retrieve message start and end positions
4320       int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
4321       int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1;
4322       // at most beginning of next task
4323       if (max_value < msgStart) {
4324         max_value = msgStart; // would only occur if tag is before EOF.
4325       }
4326       int end = -1;
4327       char c;
4328       for (int j = msgStart; j < max_value; j++) {
4329         if ((c = src[j]) == '\n' || c == '\r') {
4330           end = j - 1;
4331           break;
4332         }
4333       }
4334       if (end == -1) {
4335         for (int j = max_value; j > msgStart; j--) {
4336           if ((c = src[j]) == '*') {
4337             end = j - 1;
4338             break;
4339           }
4340         }
4341         if (end == -1)
4342           end = max_value;
4343       }
4344       if (msgStart == end)
4345         continue; // empty
4346       // trim the message
4347       while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
4348         end--;
4349       while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end)
4350         msgStart++;
4351       // update the end position of the task
4352       this.foundTaskPositions[i][1] = end;
4353       // get the message source
4354       final int messageLength = end - msgStart + 1;
4355       char[] message = new char[messageLength];
4356       System.arraycopy(src, msgStart, message, 0, messageLength);
4357       this.foundTaskMessages[i] = message;
4358     }
4359   }
4360
4361   // chech presence of task: tags
4362   //  public void checkTaskTag(int commentStart, int commentEnd) {
4363   //    // only look for newer task: tags
4364   //    if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
4365   //      return;
4366   //    }
4367   //    int foundTaskIndex = this.foundTaskCount;
4368   //    nextChar: for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) {
4369   //      char[] tag = null;
4370   //      char[] priority = null;
4371   //      // check for tag occurrence
4372   //      nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) {
4373   //        tag = this.taskTags[itag];
4374   //        priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null;
4375   //        int tagLength = tag.length;
4376   //        for (int t = 0; t < tagLength; t++) {
4377   //          if (this.source[i + t] != tag[t])
4378   //            continue nextTag;
4379   //        }
4380   //        if (this.foundTaskTags == null) {
4381   //          this.foundTaskTags = new char[5][];
4382   //          this.foundTaskMessages = new char[5][];
4383   //          this.foundTaskPriorities = new char[5][];
4384   //          this.foundTaskPositions = new int[5][];
4385   //        } else if (this.foundTaskCount == this.foundTaskTags.length) {
4386   //          System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
4387   //          System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0,
4388   //              this.foundTaskCount);
4389   //          System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0,
4390   //              this.foundTaskCount);
4391   //          System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0,
4392   //              this.foundTaskCount);
4393   //        }
4394   //        this.foundTaskTags[this.foundTaskCount] = tag;
4395   //        this.foundTaskPriorities[this.foundTaskCount] = priority;
4396   //        this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
4397   //        this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
4398   //        this.foundTaskCount++;
4399   //        i += tagLength - 1; // will be incremented when looping
4400   //      }
4401   //    }
4402   //    for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
4403   //      // retrieve message start and end positions
4404   //      int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
4405   //      int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1;
4406   //      // at most beginning of next task
4407   //      if (max_value < msgStart)
4408   //        max_value = msgStart; // would only occur if tag is before EOF.
4409   //      int end = -1;
4410   //      char c;
4411   //      for (int j = msgStart; j < max_value; j++) {
4412   //        if ((c = this.source[j]) == '\n' || c == '\r') {
4413   //          end = j - 1;
4414   //          break;
4415   //        }
4416   //      }
4417   //      if (end == -1) {
4418   //        for (int j = max_value; j > msgStart; j--) {
4419   //          if ((c = this.source[j]) == '*') {
4420   //            end = j - 1;
4421   //            break;
4422   //          }
4423   //        }
4424   //        if (end == -1)
4425   //          end = max_value;
4426   //      }
4427   //      if (msgStart == end)
4428   //        continue; // empty
4429   //      // trim the message
4430   //      while (CharOperation.isWhitespace(source[end]) && msgStart <= end)
4431   //        end--;
4432   //      while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end)
4433   //        msgStart++;
4434   //      // update the end position of the task
4435   //      this.foundTaskPositions[i][1] = end;
4436   //      // get the message source
4437   //      final int messageLength = end - msgStart + 1;
4438   //      char[] message = new char[messageLength];
4439   //      System.arraycopy(source, msgStart, message, 0, messageLength);
4440   //      this.foundTaskMessages[i] = message;
4441   //    }
4442   //  }
4443 }