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
 
   6  * Contributors: IBM Corporation - initial API and implementation
 
   7  **********************************************************************************************************************************/
 
   8 package net.sourceforge.phpdt.internal.compiler.parser;
 
  10 import java.util.ArrayList;
 
  11 import java.util.Iterator;
 
  12 import java.util.List;
 
  14 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  15 import net.sourceforge.phpdt.core.compiler.IScanner;
 
  16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 
  17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 
  18 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
 
  19 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
 
  21 public class Scanner implements IScanner, ITerminalSymbols {
 
  23          * APIs ares - getNextToken() which return the current type of the token
 
  24          * (this value is not memorized by the scanner) - getCurrentTokenSource()
 
  25          * which provides with the token "REAL" source (aka all unicode have been
 
  26          * transformed into a correct char) - sourceStart gives the position into
 
  27          * the stream - currentPosition-1 gives the sourceEnd position into the
 
  31         // private boolean assertMode;
 
  32         public boolean useAssertAsAnIndentifier = false;
 
  34         // flag indicating if processed source contains occurrences of keyword
 
  36         public boolean containsAssertKeyword = false;
 
  38         public boolean recordLineSeparator;
 
  40         public boolean ignorePHPOneLiner = false;
 
  42         public boolean phpMode = false;
 
  45          * This token is set to TokenName.echo if a short tag block begins (i.e.
 
  46          * >?= ... ) Directly after the "=" character the
 
  47          * getNextToken() method returns TokenName.INLINE_HTML In the next call to
 
  48          * the getNextToken() method the value of fFillerToken (==TokenName.echo) is
 
  52         TokenName fFillerToken = TokenName.EOF;
 
  54         public char currentCharacter;
 
  56         public int startPosition;
 
  58         public int currentPosition;
 
  60         public int initialPosition, eofPosition;
 
  62         // after this position eof are generated instead of real token from the
 
  64         public boolean tokenizeComments;
 
  66         public boolean tokenizeWhiteSpace;
 
  68         public boolean tokenizeStrings;
 
  70         // source should be viewed as a window (aka a part)
 
  71         // of a entire very large stream
 
  75         public char[] withoutUnicodeBuffer;
 
  77         public int withoutUnicodePtr;
 
  79         // when == 0 ==> no unicode in the current token
 
  80         public boolean unicodeAsBackSlash = false;
 
  82         public boolean scanningFloatLiteral = false;
 
  84         // support for /** comments
 
  85         public int[] commentStops = new int[10];
 
  87         public int[] commentStarts = new int[10];
 
  89         public int commentPtr = -1; // no comment test with commentPtr value -1
 
  91         protected int lastCommentLinePosition = -1;
 
  93         // diet parsing support - jump over some method body when requested
 
  94         public boolean diet = false;
 
  96         // support for the poor-line-debuggers ....
 
  97         // remember the position of the cr/lf
 
  98         public int[] lineEnds = new int[250];
 
 100         public int linePtr = -1;
 
 102         public boolean wasAcr = false;
 
 104         public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
 
 106         public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
 
 108         public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
 
 110         public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$
 
 112         public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
 
 114         public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
 
 116         public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
 
 118         public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
 
 120         public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
 
 122         public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
 
 124         public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
 
 126         public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
 
 128         // ----------------optimized identifier managment------------------
 
 129         static final char[] charArray_a = new char[] { 'a' },
 
 130                         charArray_b = new char[] { 'b' }, charArray_c = new char[] { 'c' },
 
 131                         charArray_d = new char[] { 'd' }, charArray_e = new char[] { 'e' },
 
 132                         charArray_f = new char[] { 'f' }, charArray_g = new char[] { 'g' },
 
 133                         charArray_h = new char[] { 'h' }, charArray_i = new char[] { 'i' },
 
 134                         charArray_j = new char[] { 'j' }, charArray_k = new char[] { 'k' },
 
 135                         charArray_l = new char[] { 'l' }, charArray_m = new char[] { 'm' },
 
 136                         charArray_n = new char[] { 'n' }, charArray_o = new char[] { 'o' },
 
 137                         charArray_p = new char[] { 'p' }, charArray_q = new char[] { 'q' },
 
 138                         charArray_r = new char[] { 'r' }, charArray_s = new char[] { 's' },
 
 139                         charArray_t = new char[] { 't' }, charArray_u = new char[] { 'u' },
 
 140                         charArray_v = new char[] { 'v' }, charArray_w = new char[] { 'w' },
 
 141                         charArray_x = new char[] { 'x' }, charArray_y = new char[] { 'y' },
 
 142                         charArray_z = new char[] { 'z' };
 
 144         static final char[] charArray_va = new char[] { '$', 'a' },
 
 145                         charArray_vb = new char[] { '$', 'b' }, charArray_vc = new char[] {
 
 146                                         '$', 'c' }, charArray_vd = new char[] { '$', 'd' },
 
 147                         charArray_ve = new char[] { '$', 'e' }, charArray_vf = new char[] {
 
 148                                         '$', 'f' }, charArray_vg = new char[] { '$', 'g' },
 
 149                         charArray_vh = new char[] { '$', 'h' }, charArray_vi = new char[] {
 
 150                                         '$', 'i' }, charArray_vj = new char[] { '$', 'j' },
 
 151                         charArray_vk = new char[] { '$', 'k' }, charArray_vl = new char[] {
 
 152                                         '$', 'l' }, charArray_vm = new char[] { '$', 'm' },
 
 153                         charArray_vn = new char[] { '$', 'n' }, charArray_vo = new char[] {
 
 154                                         '$', 'o' }, charArray_vp = new char[] { '$', 'p' },
 
 155                         charArray_vq = new char[] { '$', 'q' }, charArray_vr = new char[] {
 
 156                                         '$', 'r' }, charArray_vs = new char[] { '$', 's' },
 
 157                         charArray_vt = new char[] { '$', 't' }, charArray_vu = new char[] {
 
 158                                         '$', 'u' }, charArray_vv = new char[] { '$', 'v' },
 
 159                         charArray_vw = new char[] { '$', 'w' }, charArray_vx = new char[] {
 
 160                                         '$', 'x' }, charArray_vy = new char[] { '$', 'y' },
 
 161                         charArray_vz = new char[] { '$', 'z' };
 
 163         public final static int MAX_OBVIOUS = 256;
 
 165         static final int[] ObviousIdentCharNatures = new int[MAX_OBVIOUS];
 
 167         public final static int C_DOLLAR = 8;
 
 169         public final static int C_LETTER = 4;
 
 171         public final static int C_DIGIT = 3;
 
 173         public final static int C_SEPARATOR = 2;
 
 175         public final static int C_SPACE = 1;
 
 177                 for (int i = '0'; i <= '9'; i++)
 
 178                         ObviousIdentCharNatures[i] = C_DIGIT;
 
 180                 for (int i = 'a'; i <= 'z'; i++)
 
 181                         ObviousIdentCharNatures[i] = C_LETTER;
 
 182                 for (int i = 'A'; i <= 'Z'; i++)
 
 183                         ObviousIdentCharNatures[i] = C_LETTER;
 
 184                 ObviousIdentCharNatures['_'] = C_LETTER;
 
 185                 for (int i = 127; i <= 255; i++)
 
 186                         ObviousIdentCharNatures[i] = C_LETTER;
 
 188                 ObviousIdentCharNatures['$'] = C_DOLLAR;
 
 190                 ObviousIdentCharNatures[10] = C_SPACE; // \ u000a: LINE FEED
 
 191                 ObviousIdentCharNatures[12] = C_SPACE; // \ u000c: FORM FEED
 
 192                 ObviousIdentCharNatures[13] = C_SPACE; // \ u000d: CARRIAGE RETURN
 
 193                 ObviousIdentCharNatures[32] = C_SPACE; // \ u0020: SPACE
 
 194                 ObviousIdentCharNatures[9] = C_SPACE; // \ u0009: HORIZONTAL
 
 197                 ObviousIdentCharNatures['.'] = C_SEPARATOR;
 
 198                 ObviousIdentCharNatures[':'] = C_SEPARATOR;
 
 199                 ObviousIdentCharNatures[';'] = C_SEPARATOR;
 
 200                 ObviousIdentCharNatures[','] = C_SEPARATOR;
 
 201                 ObviousIdentCharNatures['['] = C_SEPARATOR;
 
 202                 ObviousIdentCharNatures[']'] = C_SEPARATOR;
 
 203                 ObviousIdentCharNatures['('] = C_SEPARATOR;
 
 204                 ObviousIdentCharNatures[')'] = C_SEPARATOR;
 
 205                 ObviousIdentCharNatures['{'] = C_SEPARATOR;
 
 206                 ObviousIdentCharNatures['}'] = C_SEPARATOR;
 
 207                 ObviousIdentCharNatures['+'] = C_SEPARATOR;
 
 208                 ObviousIdentCharNatures['-'] = C_SEPARATOR;
 
 209                 ObviousIdentCharNatures['*'] = C_SEPARATOR;
 
 210                 ObviousIdentCharNatures['/'] = C_SEPARATOR;
 
 211                 ObviousIdentCharNatures['='] = C_SEPARATOR;
 
 212                 ObviousIdentCharNatures['&'] = C_SEPARATOR;
 
 213                 ObviousIdentCharNatures['|'] = C_SEPARATOR;
 
 214                 ObviousIdentCharNatures['?'] = C_SEPARATOR;
 
 215                 ObviousIdentCharNatures['<'] = C_SEPARATOR;
 
 216                 ObviousIdentCharNatures['>'] = C_SEPARATOR;
 
 217                 ObviousIdentCharNatures['!'] = C_SEPARATOR;
 
 218                 ObviousIdentCharNatures['%'] = C_SEPARATOR;
 
 219                 ObviousIdentCharNatures['^'] = C_SEPARATOR;
 
 220                 ObviousIdentCharNatures['~'] = C_SEPARATOR;
 
 221                 ObviousIdentCharNatures['"'] = C_SEPARATOR;
 
 222                 ObviousIdentCharNatures['\''] = C_SEPARATOR;
 
 225         static final char[] initCharArray = new char[] { '\u0000', '\u0000',
 
 226                         '\u0000', '\u0000', '\u0000', '\u0000' };
 
 228         static final int TableSize = 30, InternalTableSize = 6;
 
 230         // 30*6 = 180 entries
 
 231         public static final int OptimizedLength = 6;
 
 234         final char[][][][] charArray_length = new char[OptimizedLength][TableSize][InternalTableSize][];
 
 236         // support for detecting non-externalized string literals
 
 237         int currentLineNr = -1;
 
 239         int previousLineNr = -1;
 
 241         NLSLine currentLine = null;
 
 243         List lines = new ArrayList();
 
 245         public static final String TAG_PREFIX = "//$NON-NLS-"; //$NON-NLS-1$
 
 247         public static final int TAG_PREFIX_LENGTH = TAG_PREFIX.length();
 
 249         public static final String TAG_POSTFIX = "$"; //$NON-NLS-1$
 
 251         public static final int TAG_POSTFIX_LENGTH = TAG_POSTFIX.length();
 
 253         public StringLiteral[] nonNLSStrings = null;
 
 255         public boolean checkNonExternalizedStringLiterals = true;
 
 257         public boolean wasNonExternalizedStringLiteral = false;
 
 260                 for (int i = 0; i < 6; i++) {
 
 261                         for (int j = 0; j < TableSize; j++) {
 
 262                                 for (int k = 0; k < InternalTableSize; k++) {
 
 263                                         charArray_length[i][j][k] = initCharArray;
 
 269         static int newEntry2 = 0, newEntry3 = 0, newEntry4 = 0, newEntry5 = 0,
 
 272         public static final int RoundBracket = 0;
 
 274         public static final int SquareBracket = 1;
 
 276         public static final int CurlyBracket = 2;
 
 278         public static final int BracketKinds = 3;
 
 281         public char[][] foundTaskTags = null;
 
 283         public char[][] foundTaskMessages;
 
 285         public char[][] foundTaskPriorities = null;
 
 287         public int[][] foundTaskPositions;
 
 289         public int foundTaskCount = 0;
 
 291         public char[][] taskTags = null;
 
 293         public char[][] taskPriorities = null;
 
 295         public boolean isTaskCaseSensitive = true;
 
 297         public static final boolean DEBUG = false;
 
 299         public static final boolean TRACE = false;
 
 301         public ICompilationUnit compilationUnit = null;
 
 304          * Determines if the specified character is permissible as the first
 
 305          * character in a PHP identifier or variable
 
 307          * The '$' character for PHP variables is regarded as a correct first
 
 311         public static boolean isPHPIdentOrVarStart(char ch) {
 
 312                 if (ch < MAX_OBVIOUS) {
 
 313                         return ObviousIdentCharNatures[ch] == C_LETTER
 
 314                                         || ObviousIdentCharNatures[ch] == C_DOLLAR;
 
 317                 // return Character.isLetter(ch) || (ch == '$') || (ch == '_') || (0x7F
 
 319                 // ch && ch <= 0xFF);
 
 323          * Determines if the specified character is permissible as the first
 
 324          * character in a PHP identifier.
 
 326          * The '$' character for PHP variables isn't regarded as the first character !
 
 328         public static boolean isPHPIdentifierStart(char ch) {
 
 329                 if (ch < MAX_OBVIOUS) {
 
 330                         return ObviousIdentCharNatures[ch] == C_LETTER;
 
 333                 // return Character.isLetter(ch) || (ch == '_') || (0x7F <= ch && ch <=
 
 338          * Determines if the specified character may be part of a PHP identifier as
 
 339          * other than the first character
 
 341         public static boolean isPHPIdentifierPart(char ch) {
 
 342                 if (ch < MAX_OBVIOUS) {
 
 343                         return ObviousIdentCharNatures[ch] == C_LETTER
 
 344                                         || ObviousIdentCharNatures[ch] == C_DIGIT;
 
 347                 // return Character.isLetterOrDigit(ch) || (ch == '_') || (0x7F <= ch &&
 
 352 //      public static boolean isSQLIdentifierPart(char ch) {
 
 353 //              if (ch < MAX_OBVIOUS) {
 
 354 //                      return ObviousIdentCharNatures[ch] == C_LETTER
 
 355 //                                      || ObviousIdentCharNatures[ch] == C_DIGIT;
 
 360         public final boolean atEnd() {
 
 361                 // This code is not relevant if source is
 
 362                 // Only a part of the real stream input
 
 363                 return source.length == currentPosition;
 
 366         public char[] getCurrentIdentifierSource() {
 
 367                 // return the token REAL source (aka unicodes are precomputed)
 
 369                 // if (withoutUnicodePtr != 0)
 
 370                 // //0 is used as a fast test flag so the real first char is in position
 
 373                 // withoutUnicodeBuffer,
 
 375                 // result = new char[withoutUnicodePtr],
 
 377                 // withoutUnicodePtr);
 
 379                 int length = currentPosition - startPosition;
 
 380                 switch (length) { // see OptimizedLength
 
 382                         return optimizedCurrentTokenSource1();
 
 384                         return optimizedCurrentTokenSource2();
 
 386                         return optimizedCurrentTokenSource3();
 
 388                         return optimizedCurrentTokenSource4();
 
 390                         return optimizedCurrentTokenSource5();
 
 392                         return optimizedCurrentTokenSource6();
 
 395                 System.arraycopy(source, startPosition, result = new char[length], 0,
 
 401         public int getCurrentTokenEndPosition() {
 
 402                 return this.currentPosition - 1;
 
 405         public final char[] getCurrentTokenSource() {
 
 406                 // Return the token REAL source (aka unicodes are precomputed)
 
 408                 // if (withoutUnicodePtr != 0)
 
 409                 // // 0 is used as a fast test flag so the real first char is in
 
 412                 // withoutUnicodeBuffer,
 
 414                 // result = new char[withoutUnicodePtr],
 
 416                 // withoutUnicodePtr);
 
 419                 System.arraycopy(source, startPosition,
 
 420                                 result = new char[length = currentPosition - startPosition], 0,
 
 426         public final char[] getCurrentTokenSource(int startPos) {
 
 427                 // Return the token REAL source (aka unicodes are precomputed)
 
 429                 // if (withoutUnicodePtr != 0)
 
 430                 // // 0 is used as a fast test flag so the real first char is in
 
 433                 // withoutUnicodeBuffer,
 
 435                 // result = new char[withoutUnicodePtr],
 
 437                 // withoutUnicodePtr);
 
 440                 System.arraycopy(source, startPos,
 
 441                                 result = new char[length = currentPosition - startPos], 0,
 
 447         public final char[] getCurrentTokenSourceString() {
 
 448                 // return the token REAL source (aka unicodes are precomputed).
 
 449                 // REMOVE the two " that are at the beginning and the end.
 
 451                 if (withoutUnicodePtr != 0)
 
 452                         // 0 is used as a fast test flag so the real first char is in
 
 454                         System.arraycopy(withoutUnicodeBuffer, 2,
 
 455                                         // 2 is 1 (real start) + 1 (to jump over the ")
 
 456                                         result = new char[withoutUnicodePtr - 2], 0,
 
 457                                         withoutUnicodePtr - 2);
 
 460                         System.arraycopy(source, startPosition + 1,
 
 461                                         result = new char[length = currentPosition - startPosition
 
 467         public final boolean equalsCurrentTokenSource(char[] word) {
 
 468                 if (word.length != currentPosition - startPosition) {
 
 471                 for (int i = 0; i < word.length; i++) {
 
 472                         if (word[i] != source[startPosition + i]) {
 
 479 //      public final char[] getRawTokenSourceEnd() {
 
 480 //              int length = this.eofPosition - this.currentPosition - 1;
 
 481 //              char[] sourceEnd = new char[length];
 
 482 //              System.arraycopy(this.source, this.currentPosition, sourceEnd, 0,
 
 487         public int getCurrentTokenStartPosition() {
 
 488                 return this.startPosition;
 
 491 //      public final String getCurrentStringLiteral() {
 
 492 //              char[] result = getCurrentStringLiteralSource();
 
 493 //              return new String(result);
 
 496         public final char[] getCurrentStringLiteralSource() {
 
 497                 // Return the token REAL source (aka unicodes are precomputed)
 
 498                 if (startPosition + 1 >= currentPosition) {
 
 504                                 .arraycopy(source, startPosition + 1,
 
 505                                                 result = new char[length = currentPosition
 
 506                                                                 - startPosition - 2], 0, length);
 
 511 //      public final char[] getCurrentStringLiteralSource(int startPos) {
 
 512 //              // Return the token REAL source (aka unicodes are precomputed)
 
 515 //              System.arraycopy(source, startPos + 1,
 
 516 //                              result = new char[length = currentPosition - startPos - 2], 0,
 
 523          * Search the source position corresponding to the end of a given line
 
 526          * Line numbers are 1-based, and relative to the scanner initialPosition.
 
 527          * Character positions are 0-based.
 
 529          * In case the given line number is inconsistent, answers -1.
 
 531         public final int getLineEnd(int lineNumber) {
 
 532                 if (lineEnds == null)
 
 534                 if (lineNumber >= lineEnds.length)
 
 538                 if (lineNumber == lineEnds.length - 1)
 
 540                 return lineEnds[lineNumber - 1];
 
 541                 // next line start one character behind the lineEnd of the previous line
 
 545          * Search the source position corresponding to the beginning of a given line
 
 548          * Line numbers are 1-based, and relative to the scanner initialPosition.
 
 549          * Character positions are 0-based.
 
 551          * e.g. getLineStart(1) --> 0 i.e. first line starts at character 0.
 
 553          * In case the given line number is inconsistent, answers -1.
 
 555         public final int getLineStart(int lineNumber) {
 
 556                 if (lineEnds == null)
 
 558                 if (lineNumber >= lineEnds.length)
 
 563                         return initialPosition;
 
 564                 return lineEnds[lineNumber - 2] + 1;
 
 565                 // next line start one character behind the lineEnd of the previous line
 
 568         public final boolean getNextChar(char testedChar) {
 
 570                 // handle the case of unicode.
 
 571                 // when a unicode appears then we must use a buffer that holds char
 
 573                 // At the end of this method currentCharacter holds the new visited char
 
 574                 // and currentPosition points right next after it
 
 575                 // Both previous lines are true if the currentCharacter is == to the
 
 577                 // On false, no side effect has occured.
 
 578                 // ALL getNextChar.... ARE OPTIMIZED COPIES
 
 579                 int temp = currentPosition;
 
 581                         currentCharacter = source[currentPosition++];
 
 582                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
 583                         // && (source[currentPosition] == 'u')) {
 
 584                         // //-------------unicode traitement ------------
 
 585                         // int c1, c2, c3, c4;
 
 586                         // int unicodeSize = 6;
 
 587                         // currentPosition++;
 
 588                         // while (source[currentPosition] == 'u') {
 
 589                         // currentPosition++;
 
 593                         // if (((c1 = Character.getNumericValue(source[currentPosition++]))
 
 596                         // || ((c2 = Character.getNumericValue(source[currentPosition++])) >
 
 599                         // || ((c3 = Character.getNumericValue(source[currentPosition++])) >
 
 602                         // || ((c4 = Character.getNumericValue(source[currentPosition++])) >
 
 605                         // currentPosition = temp;
 
 609                         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
 610                         // if (currentCharacter != testedChar) {
 
 611                         // currentPosition = temp;
 
 614                         // unicodeAsBackSlash = currentCharacter == '\\';
 
 616                         // //need the unicode buffer
 
 617                         // if (withoutUnicodePtr == 0) {
 
 618                         // //buffer all the entries that have been left aside....
 
 619                         // withoutUnicodePtr = currentPosition - unicodeSize -
 
 624                         // withoutUnicodeBuffer,
 
 626                         // withoutUnicodePtr);
 
 628                         // //fill the buffer with the char
 
 629                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 632                         // } //-------------end unicode traitement--------------
 
 634                         if (currentCharacter != testedChar) {
 
 635                                 currentPosition = temp;
 
 638                         unicodeAsBackSlash = false;
 
 639                         // if (withoutUnicodePtr != 0)
 
 640                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 643                 } catch (IndexOutOfBoundsException e) {
 
 644                         unicodeAsBackSlash = false;
 
 645                         currentPosition = temp;
 
 650         public final int getNextChar(char testedChar1, char testedChar2) {
 
 651                 // INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
 
 652                 // test can be done with (x==0) for the first and (x>0) for the second
 
 653                 // handle the case of unicode.
 
 654                 // when a unicode appears then we must use a buffer that holds char
 
 656                 // At the end of this method currentCharacter holds the new visited char
 
 657                 // and currentPosition points right next after it
 
 658                 // Both previous lines are true if the currentCharacter is == to the
 
 660                 // On false, no side effect has occured.
 
 661                 // ALL getNextChar.... ARE OPTIMIZED COPIES
 
 662                 int temp = currentPosition;
 
 665                         currentCharacter = source[currentPosition++];
 
 666                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
 667                         // && (source[currentPosition] == 'u')) {
 
 668                         // //-------------unicode traitement ------------
 
 669                         // int c1, c2, c3, c4;
 
 670                         // int unicodeSize = 6;
 
 671                         // currentPosition++;
 
 672                         // while (source[currentPosition] == 'u') {
 
 673                         // currentPosition++;
 
 677                         // if (((c1 = Character.getNumericValue(source[currentPosition++]))
 
 680                         // || ((c2 = Character.getNumericValue(source[currentPosition++])) >
 
 683                         // || ((c3 = Character.getNumericValue(source[currentPosition++])) >
 
 686                         // || ((c4 = Character.getNumericValue(source[currentPosition++])) >
 
 689                         // currentPosition = temp;
 
 693                         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
 694                         // if (currentCharacter == testedChar1)
 
 696                         // else if (currentCharacter == testedChar2)
 
 699                         // currentPosition = temp;
 
 703                         // //need the unicode buffer
 
 704                         // if (withoutUnicodePtr == 0) {
 
 705                         // //buffer all the entries that have been left aside....
 
 706                         // withoutUnicodePtr = currentPosition - unicodeSize -
 
 711                         // withoutUnicodeBuffer,
 
 713                         // withoutUnicodePtr);
 
 715                         // //fill the buffer with the char
 
 716                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 718                         // } //-------------end unicode traitement--------------
 
 720                         if (currentCharacter == testedChar1)
 
 722                         else if (currentCharacter == testedChar2)
 
 725                                 currentPosition = temp;
 
 728                         // if (withoutUnicodePtr != 0)
 
 729                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 732                 } catch (IndexOutOfBoundsException e) {
 
 733                         currentPosition = temp;
 
 738         public final boolean getNextCharAsDigit() {
 
 740                 // handle the case of unicode.
 
 741                 // when a unicode appears then we must use a buffer that holds char
 
 743                 // At the end of this method currentCharacter holds the new visited char
 
 744                 // and currentPosition points right next after it
 
 745                 // Both previous lines are true if the currentCharacter is a digit
 
 746                 // On false, no side effect has occured.
 
 747                 // ALL getNextChar.... ARE OPTIMIZED COPIES
 
 748                 int temp = currentPosition;
 
 750                         currentCharacter = source[currentPosition++];
 
 751                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
 752                         // && (source[currentPosition] == 'u')) {
 
 753                         // //-------------unicode traitement ------------
 
 754                         // int c1, c2, c3, c4;
 
 755                         // int unicodeSize = 6;
 
 756                         // currentPosition++;
 
 757                         // while (source[currentPosition] == 'u') {
 
 758                         // currentPosition++;
 
 762                         // if (((c1 = Character.getNumericValue(source[currentPosition++]))
 
 765                         // || ((c2 = Character.getNumericValue(source[currentPosition++])) >
 
 768                         // || ((c3 = Character.getNumericValue(source[currentPosition++])) >
 
 771                         // || ((c4 = Character.getNumericValue(source[currentPosition++])) >
 
 774                         // currentPosition = temp;
 
 778                         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
 779                         // if (!Character.isDigit(currentCharacter)) {
 
 780                         // currentPosition = temp;
 
 784                         // //need the unicode buffer
 
 785                         // if (withoutUnicodePtr == 0) {
 
 786                         // //buffer all the entries that have been left aside....
 
 787                         // withoutUnicodePtr = currentPosition - unicodeSize -
 
 792                         // withoutUnicodeBuffer,
 
 794                         // withoutUnicodePtr);
 
 796                         // //fill the buffer with the char
 
 797                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 799                         // } //-------------end unicode traitement--------------
 
 801                         if (!Character.isDigit(currentCharacter)) {
 
 802                                 currentPosition = temp;
 
 805                         // if (withoutUnicodePtr != 0)
 
 806                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 809                 } catch (IndexOutOfBoundsException e) {
 
 810                         currentPosition = temp;
 
 815         public final boolean getNextCharAsDigit(int radix) {
 
 817                 // handle the case of unicode.
 
 818                 // when a unicode appears then we must use a buffer that holds char
 
 820                 // At the end of this method currentCharacter holds the new visited char
 
 821                 // and currentPosition points right next after it
 
 822                 // Both previous lines are true if the currentCharacter is a digit base
 
 825                 // On false, no side effect has occured.
 
 826                 // ALL getNextChar.... ARE OPTIMIZED COPIES
 
 827                 int temp = currentPosition;
 
 829                         currentCharacter = source[currentPosition++];
 
 830                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
 831                         // && (source[currentPosition] == 'u')) {
 
 832                         // //-------------unicode traitement ------------
 
 833                         // int c1, c2, c3, c4;
 
 834                         // int unicodeSize = 6;
 
 835                         // currentPosition++;
 
 836                         // while (source[currentPosition] == 'u') {
 
 837                         // currentPosition++;
 
 841                         // if (((c1 = Character.getNumericValue(source[currentPosition++]))
 
 844                         // || ((c2 = Character.getNumericValue(source[currentPosition++])) >
 
 847                         // || ((c3 = Character.getNumericValue(source[currentPosition++])) >
 
 850                         // || ((c4 = Character.getNumericValue(source[currentPosition++])) >
 
 853                         // currentPosition = temp;
 
 857                         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
 858                         // if (Character.digit(currentCharacter, radix) == -1) {
 
 859                         // currentPosition = temp;
 
 863                         // //need the unicode buffer
 
 864                         // if (withoutUnicodePtr == 0) {
 
 865                         // //buffer all the entries that have been left aside....
 
 866                         // withoutUnicodePtr = currentPosition - unicodeSize -
 
 871                         // withoutUnicodeBuffer,
 
 873                         // withoutUnicodePtr);
 
 875                         // //fill the buffer with the char
 
 876                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 878                         // } //-------------end unicode traitement--------------
 
 880                         if (Character.digit(currentCharacter, radix) == -1) {
 
 881                                 currentPosition = temp;
 
 884                         // if (withoutUnicodePtr != 0)
 
 885                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 888                 } catch (IndexOutOfBoundsException e) {
 
 889                         currentPosition = temp;
 
 894         public boolean getNextCharAsJavaIdentifierPart() {
 
 896                 // handle the case of unicode.
 
 897                 // when a unicode appears then we must use a buffer that holds char
 
 899                 // At the end of this method currentCharacter holds the new visited char
 
 900                 // and currentPosition points right next after it
 
 901                 // Both previous lines are true if the currentCharacter is a
 
 902                 // JavaIdentifierPart
 
 903                 // On false, no side effect has occured.
 
 904                 // ALL getNextChar.... ARE OPTIMIZED COPIES
 
 905                 int temp = currentPosition;
 
 907                         currentCharacter = source[currentPosition++];
 
 908                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
 909                         // && (source[currentPosition] == 'u')) {
 
 910                         // //-------------unicode traitement ------------
 
 911                         // int c1, c2, c3, c4;
 
 912                         // int unicodeSize = 6;
 
 913                         // currentPosition++;
 
 914                         // while (source[currentPosition] == 'u') {
 
 915                         // currentPosition++;
 
 919                         // if (((c1 = Character.getNumericValue(source[currentPosition++]))
 
 922                         // || ((c2 = Character.getNumericValue(source[currentPosition++])) >
 
 925                         // || ((c3 = Character.getNumericValue(source[currentPosition++])) >
 
 928                         // || ((c4 = Character.getNumericValue(source[currentPosition++])) >
 
 931                         // currentPosition = temp;
 
 935                         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
 936                         // if (!isPHPIdentifierPart(currentCharacter)) {
 
 937                         // currentPosition = temp;
 
 941                         // //need the unicode buffer
 
 942                         // if (withoutUnicodePtr == 0) {
 
 943                         // //buffer all the entries that have been left aside....
 
 944                         // withoutUnicodePtr = currentPosition - unicodeSize -
 
 949                         // withoutUnicodeBuffer,
 
 951                         // withoutUnicodePtr);
 
 953                         // //fill the buffer with the char
 
 954                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 956                         // } //-------------end unicode traitement--------------
 
 958                         if (!isPHPIdentifierPart(currentCharacter)) {
 
 959                                 currentPosition = temp;
 
 962                         // if (withoutUnicodePtr != 0)
 
 963                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
 966                 } catch (IndexOutOfBoundsException e) {
 
 967                         currentPosition = temp;
 
 972         public TokenName getCastOrParen() {
 
 973                 int tempPosition = currentPosition;
 
 974                 char tempCharacter = currentCharacter;
 
 975                 TokenName tempToken = TokenName.LPAREN;
 
 976                 boolean found = false;
 
 977                 StringBuffer buf = new StringBuffer();
 
 980                                 currentCharacter = source[currentPosition++];
 
 981                         } while (currentCharacter == ' ' || currentCharacter == '\t');
 
 982                         while (ObviousIdentCharNatures[currentCharacter] == C_LETTER) {
 
 983                                 // while((currentCharacter >= 'a' && currentCharacter <= 'z') ||
 
 984                                 // (currentCharacter >= 'A' && currentCharacter <= 'Z')) {
 
 985                                 buf.append(currentCharacter);
 
 986                                 currentCharacter = source[currentPosition++];
 
 988                         if (buf.length() >= 3 && buf.length() <= 7) {
 
 989                                 char[] data = buf.toString().toCharArray();
 
 991                                 switch (data.length) {
 
 994                                         if ((data[index] == 'i') && (data[++index] == 'n')
 
 995                                                         && (data[++index] == 't')) {
 
 997                                                 tempToken = TokenName.INTCAST;
 
1002                                         if ((data[index] == 'b') && (data[++index] == 'o')
 
1003                                                         && (data[++index] == 'o') && (data[++index] == 'l')) {
 
1005                                                 tempToken = TokenName.BOOLCAST;
 
1008                                                 if ((data[index] == 'r') && (data[++index] == 'e')
 
1009                                                                 && (data[++index] == 'a')
 
1010                                                                 && (data[++index] == 'l')) {
 
1012                                                         tempToken = TokenName.DOUBLECAST;
 
1017                                         // array unset float
 
1018                                         if ((data[index] == 'a') && (data[++index] == 'r')
 
1019                                                         && (data[++index] == 'r') && (data[++index] == 'a')
 
1020                                                         && (data[++index] == 'y')) {
 
1022                                                 tempToken = TokenName.ARRAYCAST;
 
1025                                                 if ((data[index] == 'u') && (data[++index] == 'n')
 
1026                                                                 && (data[++index] == 's')
 
1027                                                                 && (data[++index] == 'e')
 
1028                                                                 && (data[++index] == 't')) {
 
1030                                                         tempToken = TokenName.UNSETCAST;
 
1033                                                         if ((data[index] == 'f') && (data[++index] == 'l')
 
1034                                                                         && (data[++index] == 'o')
 
1035                                                                         && (data[++index] == 'a')
 
1036                                                                         && (data[++index] == 't')) {
 
1038                                                                 tempToken = TokenName.DOUBLECAST;
 
1044                                         // object string double
 
1045                                         if ((data[index] == 'o') && (data[++index] == 'b')
 
1046                                                         && (data[++index] == 'j') && (data[++index] == 'e')
 
1047                                                         && (data[++index] == 'c') && (data[++index] == 't')) {
 
1049                                                 tempToken = TokenName.OBJECTCAST;
 
1052                                                 if ((data[index] == 's') && (data[++index] == 't')
 
1053                                                                 && (data[++index] == 'r')
 
1054                                                                 && (data[++index] == 'i')
 
1055                                                                 && (data[++index] == 'n')
 
1056                                                                 && (data[++index] == 'g')) {
 
1058                                                         tempToken = TokenName.STRINGCAST;
 
1061                                                         if ((data[index] == 'd') && (data[++index] == 'o')
 
1062                                                                         && (data[++index] == 'u')
 
1063                                                                         && (data[++index] == 'b')
 
1064                                                                         && (data[++index] == 'l')
 
1065                                                                         && (data[++index] == 'e')) {
 
1067                                                                 tempToken = TokenName.DOUBLECAST;
 
1074                                         if ((data[index] == 'b') && (data[++index] == 'o')
 
1075                                                         && (data[++index] == 'o') && (data[++index] == 'l')
 
1076                                                         && (data[++index] == 'e') && (data[++index] == 'a')
 
1077                                                         && (data[++index] == 'n')) {
 
1079                                                 tempToken = TokenName.BOOLCAST;
 
1082                                                 if ((data[index] == 'i') && (data[++index] == 'n')
 
1083                                                                 && (data[++index] == 't')
 
1084                                                                 && (data[++index] == 'e')
 
1085                                                                 && (data[++index] == 'g')
 
1086                                                                 && (data[++index] == 'e')
 
1087                                                                 && (data[++index] == 'r')) {
 
1089                                                         tempToken = TokenName.INTCAST;
 
1095                                         while (currentCharacter == ' ' || currentCharacter == '\t') {
 
1096                                                 currentCharacter = source[currentPosition++];
 
1098                                         if (currentCharacter == ')') {
 
1103                 } catch (IndexOutOfBoundsException e) {
 
1105                 currentCharacter = tempCharacter;
 
1106                 currentPosition = tempPosition;
 
1107                 return TokenName.LPAREN;
 
1114         public void consumeStringInterpolated() throws InvalidInputException {
 
1116                         // consume next character
 
1117                         unicodeAsBackSlash = false;
 
1118                         currentCharacter = source[currentPosition++];
 
1119                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
1120                         // && (source[currentPosition] == 'u')) {
 
1121                         // getNextUnicodeChar();
 
1123                         // if (withoutUnicodePtr != 0) {
 
1124                         // withoutUnicodeBuffer[++withoutUnicodePtr] =
 
1125                         // currentCharacter;
 
1128                         while (currentCharacter != '`') {
 
1129                                 /** ** in PHP \r and \n are valid in string literals *** */
 
1130                                 // if ((currentCharacter == '\n')
 
1131                                 // || (currentCharacter == '\r')) {
 
1132                                 // // relocate if finding another quote fairly close: thus
 
1134                                 // '/u000D' will be fully consumed
 
1135                                 // for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 
1136                                 // if (currentPosition + lookAhead == source.length)
 
1138                                 // if (source[currentPosition + lookAhead] == '\n')
 
1140                                 // if (source[currentPosition + lookAhead] == '\"') {
 
1141                                 // currentPosition += lookAhead + 1;
 
1145                                 // throw new InvalidInputException(INVALID_CHAR_IN_STRING);
 
1147                                 if (currentCharacter == '\\') {
 
1148                                         int escapeSize = currentPosition;
 
1149                                         boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
 
1150                                         // scanEscapeCharacter make a side effect on this value and
 
1152                                         // the previous value few lines down this one
 
1153                                         scanDoubleQuotedEscapeCharacter();
 
1154                                         escapeSize = currentPosition - escapeSize;
 
1155                                         if (withoutUnicodePtr == 0) {
 
1156                                                 // buffer all the entries that have been left aside....
 
1157                                                 withoutUnicodePtr = currentPosition - escapeSize - 1
 
1159                                                 System.arraycopy(source, startPosition,
 
1160                                                                 withoutUnicodeBuffer, 1, withoutUnicodePtr);
 
1161                                                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1162                                         } else { // overwrite the / in the buffer
 
1163                                                 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
 
1164                                                 if (backSlashAsUnicodeInString) { // there are TWO \
 
1166                                                         // where only one is correct
 
1167                                                         withoutUnicodePtr--;
 
1170                                 } else if ((currentCharacter == '\r')
 
1171                                                 || (currentCharacter == '\n')) {
 
1172                                         if (recordLineSeparator) {
 
1173                                                 pushLineSeparator();
 
1176                                 // consume next character
 
1177                                 unicodeAsBackSlash = false;
 
1178                                 currentCharacter = source[currentPosition++];
 
1179                                 // if (((currentCharacter = source[currentPosition++]) == '\\')
 
1180                                 // && (source[currentPosition] == 'u')) {
 
1181                                 // getNextUnicodeChar();
 
1183                                 if (withoutUnicodePtr != 0) {
 
1184                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1188                 } catch (IndexOutOfBoundsException e) {
 
1189                         // reset end position for error reporting
 
1190                         currentPosition -= 2;
 
1191                         throw new InvalidInputException(UNTERMINATED_STRING);
 
1192                 } catch (InvalidInputException e) {
 
1193                         if (e.getMessage().equals(INVALID_ESCAPE)) {
 
1194                                 // relocate if finding another quote fairly close: thus unicode
 
1195                                 // '/u000D' will be fully consumed
 
1196                                 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 
1197                                         if (currentPosition + lookAhead == source.length)
 
1199                                         if (source[currentPosition + lookAhead] == '\n')
 
1201                                         if (source[currentPosition + lookAhead] == '`') {
 
1202                                                 currentPosition += lookAhead + 1;
 
1209                 if (checkNonExternalizedStringLiterals) { // check for presence of NLS
 
1211                         // //$NON-NLS-?$ where ? is an
 
1213                         if (currentLine == null) {
 
1214                                 currentLine = new NLSLine();
 
1215                                 lines.add(currentLine);
 
1217                         currentLine.add(new StringLiteral(getCurrentTokenSourceString(),
 
1218                                         startPosition, currentPosition - 1));
 
1222         public void consumeStringConstant() throws InvalidInputException {
 
1224                         // consume next character
 
1225                         unicodeAsBackSlash = false;
 
1226                         currentCharacter = source[currentPosition++];
 
1227                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
1228                         // && (source[currentPosition] == 'u')) {
 
1229                         // getNextUnicodeChar();
 
1231                         // if (withoutUnicodePtr != 0) {
 
1232                         // withoutUnicodeBuffer[++withoutUnicodePtr] =
 
1233                         // currentCharacter;
 
1236                         while (currentCharacter != '\'') {
 
1237                                 /** ** in PHP \r and \n are valid in string literals *** */
 
1238                                 // if ((currentCharacter == '\n')
 
1239                                 // || (currentCharacter == '\r')) {
 
1240                                 // // relocate if finding another quote fairly close: thus
 
1242                                 // '/u000D' will be fully consumed
 
1243                                 // for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 
1244                                 // if (currentPosition + lookAhead == source.length)
 
1246                                 // if (source[currentPosition + lookAhead] == '\n')
 
1248                                 // if (source[currentPosition + lookAhead] == '\"') {
 
1249                                 // currentPosition += lookAhead + 1;
 
1253                                 // throw new InvalidInputException(INVALID_CHAR_IN_STRING);
 
1255                                 if (currentCharacter == '\\') {
 
1256                                         int escapeSize = currentPosition;
 
1257                                         boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
 
1258                                         // scanEscapeCharacter make a side effect on this value and
 
1260                                         // the previous value few lines down this one
 
1261                                         scanSingleQuotedEscapeCharacter();
 
1262                                         escapeSize = currentPosition - escapeSize;
 
1263                                         if (withoutUnicodePtr == 0) {
 
1264                                                 // buffer all the entries that have been left aside....
 
1265                                                 withoutUnicodePtr = currentPosition - escapeSize - 1
 
1267                                                 System.arraycopy(source, startPosition,
 
1268                                                                 withoutUnicodeBuffer, 1, withoutUnicodePtr);
 
1269                                                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1270                                         } else { // overwrite the / in the buffer
 
1271                                                 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
 
1272                                                 if (backSlashAsUnicodeInString) { // there are TWO \
 
1274                                                         // where only one is correct
 
1275                                                         withoutUnicodePtr--;
 
1278                                 } else if ((currentCharacter == '\r')
 
1279                                                 || (currentCharacter == '\n')) {
 
1280                                         if (recordLineSeparator) {
 
1281                                                 pushLineSeparator();
 
1284                                 // consume next character
 
1285                                 unicodeAsBackSlash = false;
 
1286                                 currentCharacter = source[currentPosition++];
 
1287                                 // if (((currentCharacter = source[currentPosition++]) == '\\')
 
1288                                 // && (source[currentPosition] == 'u')) {
 
1289                                 // getNextUnicodeChar();
 
1291                                 if (withoutUnicodePtr != 0) {
 
1292                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1296                 } catch (IndexOutOfBoundsException e) {
 
1297                         // reset end position for error reporting
 
1298                         currentPosition -= 2;
 
1299                         throw new InvalidInputException(UNTERMINATED_STRING);
 
1300                 } catch (InvalidInputException e) {
 
1301                         if (e.getMessage().equals(INVALID_ESCAPE)) {
 
1302                                 // relocate if finding another quote fairly close: thus unicode
 
1303                                 // '/u000D' will be fully consumed
 
1304                                 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 
1305                                         if (currentPosition + lookAhead == source.length)
 
1307                                         if (source[currentPosition + lookAhead] == '\n')
 
1309                                         if (source[currentPosition + lookAhead] == '\'') {
 
1310                                                 currentPosition += lookAhead + 1;
 
1317                 if (checkNonExternalizedStringLiterals) { // check for presence of NLS
 
1319                         // //$NON-NLS-?$ where ? is an
 
1321                         if (currentLine == null) {
 
1322                                 currentLine = new NLSLine();
 
1323                                 lines.add(currentLine);
 
1325                         currentLine.add(new StringLiteral(getCurrentTokenSourceString(),
 
1326                                         startPosition, currentPosition - 1));
 
1334         public void consumeStringLiteral() throws InvalidInputException {
 
1336                         int openDollarBrace = 0;
 
1338                         unicodeAsBackSlash  = false;
 
1339                         currentCharacter    = source[currentPosition++];                                   // consume next character
 
1341                         while (currentCharacter != '"' ||                                          // As long as the ending '"' isn't found, or
 
1342                                openDollarBrace > 0) {                                              // the last '}' isn't found
 
1343                                 if (currentCharacter == '\\') {
 
1344                                         int     escapeSize                 = currentPosition;
 
1345                                         boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
 
1347                                         // scanEscapeCharacter make a side effect on this value and we need
 
1348                                         // the previous value few lines down this one
 
1349                                         scanDoubleQuotedEscapeCharacter ();
 
1350                                         escapeSize = currentPosition - escapeSize;
 
1352                                         if (withoutUnicodePtr == 0) {                                      // buffer all the entries that have been left aside....
 
1353                                                 withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
 
1354                                                 System.arraycopy (source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
 
1355                                                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1357                                         else {                                                             // overwrite the / in the buffer
 
1358                                                 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
 
1360                                                 if (backSlashAsUnicodeInString) {                              // there are TWO \ in the stream where only one is correct
 
1361                                                         withoutUnicodePtr--;
 
1365                                 else if (currentCharacter == '$' && source[currentPosition] == '{') {  // If found '${'
 
1367                                         currentCharacter = source[currentPosition++];                      // consume next character, or we count one open brace to much!
 
1369                                 else if (currentCharacter == '{' && source[currentPosition] == '$') {  // If found '{$'
 
1372                                 else if (currentCharacter == '}') {                                    // If found '}'
 
1375                                 else if ((currentCharacter == '\r') || (currentCharacter == '\n')) {   // In PHP \r and \n are valid in string literals
 
1376                                         if (recordLineSeparator) {
 
1377                                                 pushLineSeparator ();
 
1381                                 unicodeAsBackSlash = false;
 
1382                                 currentCharacter = source[currentPosition++];                          // consume next character
 
1384                                 if (withoutUnicodePtr != 0) {
 
1385                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
1388                 } catch (IndexOutOfBoundsException e) {
 
1389                         // reset end position for error reporting
 
1390                         currentPosition -= 2;
 
1391                         throw new InvalidInputException(UNTERMINATED_STRING);
 
1392                 } catch (InvalidInputException e) {
 
1393                         if (e.getMessage().equals(INVALID_ESCAPE)) {
 
1394                                 // relocate if finding another quote fairly close: thus unicode
 
1395                                 // '/u000D' will be fully consumed
 
1396                                 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 
1397                                         if (currentPosition + lookAhead == source.length)
 
1399                                         if (source[currentPosition + lookAhead] == '\n')
 
1401                                         if (source[currentPosition + lookAhead] == '\"') {
 
1402                                                 currentPosition += lookAhead + 1;
 
1410                 if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
 
1411                         // $NON-NLS-?$ where ? is an int.
 
1412                         if (currentLine == null) {
 
1413                                 currentLine = new NLSLine ();
 
1414                                 lines.add (currentLine);
 
1416                         currentLine.add (new StringLiteral (getCurrentTokenSourceString (), startPosition, currentPosition - 1));
 
1423         public TokenName getNextToken() throws InvalidInputException {
 
1425                         return getInlinedHTMLToken(currentPosition);
 
1427                         if (fFillerToken != TokenName.EOF) {
 
1428                                 TokenName tempToken;
 
1429                                 startPosition = currentPosition;
 
1430                                 tempToken = fFillerToken;
 
1431                                 fFillerToken = TokenName.EOF;
 
1434                         this.wasAcr = false;
 
1436                                 jumpOverMethodBody();
 
1438                                 return currentPosition > source.length ? TokenName.EOF
 
1443                                         withoutUnicodePtr = 0;
 
1444                                         // ---------Consume white space and handles
 
1445                                         // startPosition---------
 
1446                                         int whiteStart = currentPosition;
 
1447                                         startPosition = currentPosition;
 
1448                                         currentCharacter = source[currentPosition++];
 
1450                                         while ((currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) {
 
1451                                                 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
 
1452                                                         checkNonExternalizeString();
 
1454                                                         if (recordLineSeparator) {
 
1455                                                                 pushLineSeparator();
 
1460                                                 startPosition = currentPosition;
 
1461                                                 currentCharacter = source[currentPosition++];
 
1464                                         if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) {
 
1465                                                 // reposition scanner in case we are interested by
 
1468                                                 startPosition = whiteStart;
 
1469                                                 return TokenName.WHITESPACE;
 
1471                                         // little trick to get out in the middle of a source
 
1473                                         if (currentPosition > eofPosition)
 
1474                                                 return TokenName.EOF;
 
1475                                         // ---------Identify the next token-------------
 
1476                                         switch (currentCharacter) {
 
1478                                                 return getCastOrParen();
 
1480                                                 return TokenName.RPAREN;
 
1482                                                 return TokenName.LBRACE;
 
1484                                                 return TokenName.RBRACE;
 
1486                                                 return TokenName.LBRACKET;
 
1488                                                 return TokenName.RBRACKET;
 
1490                                                 return TokenName.SEMICOLON;
 
1492                                                 return TokenName.COMMA;
 
1494                                                 if (getNextChar('='))
 
1495                                                         return TokenName.DOT_EQUAL;
 
1496                                                 if (getNextCharAsDigit())
 
1497                                                         return scanNumber(true);
 
1498                                                 return TokenName.DOT;
 
1500                                             return TokenName.BACKSLASH;
 
1503                                                 if ((test = getNextChar('+', '=')) == 0)
 
1504                                                         return TokenName.PLUS_PLUS;
 
1506                                                         return TokenName.PLUS_EQUAL;
 
1507                                                 return TokenName.PLUS;
 
1511                                                 if ((test = getNextChar('-', '=')) == 0)
 
1512                                                         return TokenName.MINUS_MINUS;
 
1514                                                         return TokenName.MINUS_EQUAL;
 
1515                                                 if (getNextChar('>'))
 
1516                                                         return TokenName.MINUS_GREATER;
 
1517                                                 return TokenName.MINUS;
 
1520                                                 if (getNextChar('='))
 
1521                                                         return TokenName.TWIDDLE_EQUAL;
 
1522                                                 return TokenName.TWIDDLE;
 
1524                                                 if (getNextChar('=')) {
 
1525                                                         if (getNextChar('=')) {
 
1526                                                                 return TokenName.NOT_EQUAL_EQUAL;
 
1528                                                         return TokenName.NOT_EQUAL;
 
1530                                                 return TokenName.NOT;
 
1532                                                 if (getNextChar('='))
 
1533                                                         return TokenName.MULTIPLY_EQUAL;
 
1534                                                 return TokenName.MULTIPLY;
 
1536                                                 if (getNextChar('='))
 
1537                                                         return TokenName.REMAINDER_EQUAL;
 
1538                                                 return TokenName.REMAINDER;
 
1540                                                 int oldPosition = currentPosition;
 
1542                                                         currentCharacter = source[currentPosition++];
 
1543                                                 } catch (IndexOutOfBoundsException e) {
 
1544                                                         currentPosition = oldPosition;
 
1545                                                         return TokenName.LESS;
 
1547                                                 switch (currentCharacter) {
 
1549                                                         return TokenName.LESS_EQUAL;
 
1551                                                         return TokenName.NOT_EQUAL;
 
1553                                                         if (getNextChar('='))
 
1554                                                                 return TokenName.LEFT_SHIFT_EQUAL;
 
1555                                                         if (getNextChar('<')) {
 
1556                                                                 currentCharacter = source[currentPosition++];
 
1557                                                                 while (Character.isWhitespace(currentCharacter)) {
 
1558                                                                         currentCharacter = source[currentPosition++];
 
1560                                                                 int heredocStart = currentPosition - 1;
 
1561                                                                 int heredocLength = 0;
 
1562                                                                 if (isPHPIdentifierStart(currentCharacter)) {
 
1563                                                                         currentCharacter = source[currentPosition++];
 
1565                                                                         return TokenName.ERROR;
 
1567                                                                 while (isPHPIdentifierPart(currentCharacter)) {
 
1568                                                                         currentCharacter = source[currentPosition++];
 
1570                                                                 heredocLength = currentPosition - heredocStart
 
1572                                                                 // heredoc end-tag determination
 
1573                                                                 boolean endTag = true;
 
1576                                                                         ch = source[currentPosition++];
 
1577                                                                         if (ch == '\r' || ch == '\n') {
 
1578                                                                                 if (recordLineSeparator) {
 
1579                                                                                         pushLineSeparator();
 
1583                                                                                 for (int i = 0; i < heredocLength; i++) {
 
1584                                                                                         if (source[currentPosition + i] != source[heredocStart
 
1591                                                                                         currentPosition += heredocLength - 1;
 
1592                                                                                         currentCharacter = source[currentPosition++];
 
1593                                                                                         break; // do...while loop
 
1599                                                                 return TokenName.HEREDOC;
 
1601                                                         return TokenName.LEFT_SHIFT;
 
1603                                                 currentPosition = oldPosition;
 
1604                                                 return TokenName.LESS;
 
1608                                                 if ((test = getNextChar('=', '>')) == 0)
 
1609                                                         return TokenName.GREATER_EQUAL;
 
1611                                                         if ((test = getNextChar('=', '>')) == 0)
 
1612                                                                 return TokenName.RIGHT_SHIFT_EQUAL;
 
1613                                                         return TokenName.RIGHT_SHIFT;
 
1615                                                 return TokenName.GREATER;
 
1618                                                 if (getNextChar('=')) {
 
1619                                                         if (getNextChar('=')) {
 
1620                                                                 return TokenName.EQUAL_EQUAL_EQUAL;
 
1622                                                         return TokenName.EQUAL_EQUAL;
 
1624                                                 if (getNextChar('>'))
 
1625                                                         return TokenName.EQUAL_GREATER;
 
1626                                                 return TokenName.EQUAL;
 
1629                                                 if ((test = getNextChar('&', '=')) == 0)
 
1630                                                         return TokenName.AND_AND;
 
1632                                                         return TokenName.AND_EQUAL;
 
1633                                                 return TokenName.OP_AND;
 
1637                                                 if ((test = getNextChar('|', '=')) == 0)
 
1638                                                         return TokenName.OR_OR;
 
1640                                                         return TokenName.OR_EQUAL;
 
1641                                                 return TokenName.OP_OR;
 
1644                                                 if (getNextChar('='))
 
1645                                                         return TokenName.XOR_EQUAL;
 
1646                                                 return TokenName.OP_XOR;
 
1648                                                 if (getNextChar('>')) {
 
1650                                                         if (currentPosition == source.length) {
 
1652                                                                 return TokenName.INLINE_HTML;
 
1654                                                         return getInlinedHTMLToken(currentPosition - 2);
 
1656                                                 else if (getNextChar(':')) {
 
1657                                                         return TokenName.TERNARY_SHORT;
 
1660                                                 return TokenName.QUESTION;
 
1663                                                 if (getNextChar(':'))
 
1664                                                         return TokenName.PAAMAYIM_NEKUDOTAYIM;
 
1665                                                 return TokenName.COLON;
 
1667                                                 return TokenName.OP_AT;
 
1669                                                 consumeStringConstant();
 
1670                                                 return TokenName.STRINGSINGLEQUOTE;
 
1672                                                 // if (tokenizeStrings) {
 
1673                                                 consumeStringLiteral();
 
1674                                                 return TokenName.STRINGDOUBLEQUOTE;
 
1676                                                 // return TokenName.EncapsedString2;
 
1678                                                 // if (tokenizeStrings) {
 
1679                                                 consumeStringInterpolated();
 
1680                                                 return TokenName.STRINGINTERPOLATED;
 
1682                                                 // return TokenName.EncapsedString0;
 
1685                                                 char startChar = currentCharacter;
 
1686                                                 if (getNextChar('=') && startChar == '/') {
 
1687                                                         return TokenName.DIVIDE_EQUAL;
 
1690                                                 if ((startChar == '#')
 
1691                                                                 || (test = getNextChar('/', '*')) == 0) {
 
1693                                                         this.lastCommentLinePosition = this.currentPosition;
 
1694                                                         int endPositionForLineComment = 0;
 
1695                                                         try { // get the next char
 
1696                                                                 currentCharacter = source[currentPosition++];
 
1697                                                                 // if (((currentCharacter =
 
1698                                                                 // source[currentPosition++])
 
1700                                                                 // && (source[currentPosition] == 'u')) {
 
1701                                                                 // //-------------unicode traitement
 
1703                                                                 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
1704                                                                 // currentPosition++;
 
1705                                                                 // while (source[currentPosition] == 'u') {
 
1706                                                                 // currentPosition++;
 
1709                                                                 // Character.getNumericValue(source[currentPosition++]))
 
1713                                                                 // Character.getNumericValue(source[currentPosition++]))
 
1717                                                                 // Character.getNumericValue(source[currentPosition++]))
 
1721                                                                 // Character.getNumericValue(source[currentPosition++]))
 
1725                                                                 // InvalidInputException(INVALID_UNICODE_ESCAPE);
 
1727                                                                 // currentCharacter =
 
1728                                                                 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 +
 
1732                                                                 // handle the \\u case manually into comment
 
1733                                                                 // if (currentCharacter == '\\') {
 
1734                                                                 // if (source[currentPosition] == '\\')
 
1735                                                                 // currentPosition++;
 
1736                                                                 // } //jump over the \\
 
1737                                                                 boolean isUnicode = false;
 
1738                                                                 while (currentCharacter != '\r'
 
1739                                                                                 && currentCharacter != '\n') {
 
1740                                                                         this.lastCommentLinePosition = this.currentPosition;
 
1741                                                                         if (currentCharacter == '?') {
 
1742                                                                                 if (getNextChar('>')) {
 
1743                                                                                         // ?> breaks line comments
 
1744                                                                                         startPosition = currentPosition - 2;
 
1746                                                                                         return TokenName.INLINE_HTML;
 
1749                                                                         // get the next char
 
1751                                                                         currentCharacter = source[currentPosition++];
 
1752                                                                         // if (((currentCharacter =
 
1753                                                                         // source[currentPosition++])
 
1755                                                                         // && (source[currentPosition] == 'u')) {
 
1756                                                                         // isUnicode = true;
 
1757                                                                         // //-------------unicode traitement
 
1759                                                                         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
1760                                                                         // currentPosition++;
 
1761                                                                         // while (source[currentPosition] == 'u') {
 
1762                                                                         // currentPosition++;
 
1765                                                                         // Character.getNumericValue(source[currentPosition++]))
 
1769                                                                         // Character.getNumericValue(
 
1770                                                                         // source[currentPosition++]))
 
1774                                                                         // Character.getNumericValue(
 
1775                                                                         // source[currentPosition++]))
 
1779                                                                         // Character.getNumericValue(
 
1780                                                                         // source[currentPosition++]))
 
1784                                                                         // InvalidInputException(INVALID_UNICODE_ESCAPE);
 
1786                                                                         // currentCharacter =
 
1787                                                                         // (char) (((c1 * 16 + c2) * 16 + c3) * 16 +
 
1791                                                                         // handle the \\u case manually into comment
 
1792                                                                         // if (currentCharacter == '\\') {
 
1793                                                                         // if (source[currentPosition] == '\\')
 
1794                                                                         // currentPosition++;
 
1795                                                                         // } //jump over the \\
 
1798                                                                         endPositionForLineComment = currentPosition - 6;
 
1800                                                                         endPositionForLineComment = currentPosition - 1;
 
1802                                                                 // recordComment(false);
 
1803                                                                 recordComment(TokenName.COMMENT_LINE);
 
1804                                                                 if (this.taskTags != null)
 
1805                                                                         checkTaskTag(this.startPosition,
 
1806                                                                                         this.currentPosition);
 
1807                                                                 if ((currentCharacter == '\r')
 
1808                                                                                 || (currentCharacter == '\n')) {
 
1809                                                                         checkNonExternalizeString();
 
1810                                                                         if (recordLineSeparator) {
 
1812                                                                                         pushUnicodeLineSeparator();
 
1814                                                                                         pushLineSeparator();
 
1820                                                                 if (tokenizeComments) {
 
1822                                                                                 currentPosition = endPositionForLineComment;
 
1823                                                                                 // reset one character behind
 
1825                                                                         return TokenName.COMMENT_LINE;
 
1827                                                         } catch (IndexOutOfBoundsException e) { // an eof
 
1830                                                                 if (tokenizeComments) {
 
1832                                                                         // reset one character behind
 
1833                                                                         return TokenName.COMMENT_LINE;
 
1839                                                         // traditional and annotation comment
 
1840                                                         boolean isJavadoc = false, star = false;
 
1841                                                         // consume next character
 
1842                                                         unicodeAsBackSlash = false;
 
1843                                                         currentCharacter = source[currentPosition++];
 
1844                                                         // if (((currentCharacter =
 
1845                                                         // source[currentPosition++]) ==
 
1847                                                         // && (source[currentPosition] == 'u')) {
 
1848                                                         // getNextUnicodeChar();
 
1850                                                         // if (withoutUnicodePtr != 0) {
 
1851                                                         // withoutUnicodeBuffer[++withoutUnicodePtr] =
 
1852                                                         // currentCharacter;
 
1855                                                         if (currentCharacter == '*') {
 
1859                                                         if ((currentCharacter == '\r')
 
1860                                                                         || (currentCharacter == '\n')) {
 
1861                                                                 checkNonExternalizeString();
 
1862                                                                 if (recordLineSeparator) {
 
1863                                                                         pushLineSeparator();
 
1868                                                         try { // get the next char
 
1869                                                                 currentCharacter = source[currentPosition++];
 
1870                                                                 // if (((currentCharacter =
 
1871                                                                 // source[currentPosition++])
 
1873                                                                 // && (source[currentPosition] == 'u')) {
 
1874                                                                 // //-------------unicode traitement
 
1876                                                                 // getNextUnicodeChar();
 
1878                                                                 // handle the \\u case manually into comment
 
1879                                                                 // if (currentCharacter == '\\') {
 
1880                                                                 // if (source[currentPosition] == '\\')
 
1881                                                                 // currentPosition++;
 
1882                                                                 // //jump over the \\
 
1884                                                                 // empty comment is not a javadoc /**/
 
1885                                                                 if (currentCharacter == '/') {
 
1888                                                                 // loop until end of comment */
 
1889                                                                 while ((currentCharacter != '/') || (!star)) {
 
1890                                                                         if ((currentCharacter == '\r')
 
1891                                                                                         || (currentCharacter == '\n')) {
 
1892                                                                                 checkNonExternalizeString();
 
1893                                                                                 if (recordLineSeparator) {
 
1894                                                                                         pushLineSeparator();
 
1899                                                                         star = currentCharacter == '*';
 
1901                                                                         currentCharacter = source[currentPosition++];
 
1902                                                                         // if (((currentCharacter =
 
1903                                                                         // source[currentPosition++])
 
1905                                                                         // && (source[currentPosition] == 'u')) {
 
1906                                                                         // //-------------unicode traitement
 
1908                                                                         // getNextUnicodeChar();
 
1910                                                                         // handle the \\u case manually into comment
 
1911                                                                         // if (currentCharacter == '\\') {
 
1912                                                                         // if (source[currentPosition] == '\\')
 
1913                                                                         // currentPosition++;
 
1914                                                                         // } //jump over the \\
 
1916                                                                 // recordComment(isJavadoc);
 
1918                                                                         recordComment(TokenName.COMMENT_PHPDOC);
 
1920                                                                         recordComment(TokenName.COMMENT_BLOCK);
 
1923                                                                 if (tokenizeComments) {
 
1925                                                                                 return TokenName.COMMENT_PHPDOC;
 
1926                                                                         return TokenName.COMMENT_BLOCK;
 
1929                                                                 if (this.taskTags != null) {
 
1930                                                                         checkTaskTag(this.startPosition,
 
1931                                                                                         this.currentPosition);
 
1933                                                         } catch (IndexOutOfBoundsException e) {
 
1934                                                                 // reset end position for error reporting
 
1935                                                                 currentPosition -= 2;
 
1936                                                                 throw new InvalidInputException(
 
1937                                                                                 UNTERMINATED_COMMENT);
 
1941                                                 return TokenName.DIVIDE;
 
1945                                                         return TokenName.EOF;
 
1946                                                 // the atEnd may not be <currentPosition ==
 
1947                                                 // source.length> if
 
1948                                                 // source is only some part of a real (external) stream
 
1949                                                 throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
 
1951                                                 if (currentCharacter == '$') {
 
1952                                                         int oldPosition = currentPosition;
 
1954                                                                 currentCharacter = source[currentPosition++];
 
1955                                                                 if (isPHPIdentifierStart(currentCharacter)) {
 
1956                                                                         return scanIdentifierOrKeyword(true);
 
1958                                                                         currentPosition = oldPosition;
 
1959                                                                         return TokenName.DOLLAR;
 
1961                                                         } catch (IndexOutOfBoundsException e) {
 
1962                                                                 currentPosition = oldPosition;
 
1963                                                                 return TokenName.DOLLAR;
 
1967                                                 if (isPHPIdentifierStart(currentCharacter)) {
 
1968                                                         return scanIdentifierOrKeyword(false);
 
1971                                                 if (Character.isDigit(currentCharacter)) {
 
1972                                                         return scanNumber(false);
 
1975                                                 return TokenName.ERROR;
 
1978                         } // -----------------end switch while try--------------------
 
1979                         catch (IndexOutOfBoundsException e) {
 
1982                 return TokenName.EOF;
 
1987          * @throws InvalidInputException
 
1989         private TokenName getInlinedHTMLToken(int start) throws InvalidInputException {
 
1990                 boolean phpShortTag = false; // true, if <?= detected
 
1991                 if (currentPosition > source.length) {
 
1992                         currentPosition = source.length;
 
1993                         return TokenName.EOF;
 
1995                 startPosition = start;
 
1998                                 currentCharacter = source[currentPosition++];
 
1999                                 if (currentCharacter == '<') {
 
2000                                         if (getNextChar('?')) {
 
2001                                                 currentCharacter = source[currentPosition++];
 
2002                                                 if ((currentCharacter != 'P')
 
2003                                                                 && (currentCharacter != 'p')) {
 
2004                                                         if (currentCharacter != '=') { // <?=
 
2006                                                                 phpShortTag = false;
 
2011                                                         if (ignorePHPOneLiner) { // for CodeFormatter
 
2012                                                                 if (lookAheadLinePHPTag() == TokenName.INLINE_HTML) {
 
2015                                                                                 fFillerToken = TokenName.ECHO_INVISIBLE;
 
2017                                                                         return TokenName.INLINE_HTML;
 
2020                                                                 boolean foundXML = false;
 
2021                                                                 if (getNextChar('X', 'x') >= 0) {
 
2022                                                                         if (getNextChar('M', 'm') >= 0) {
 
2023                                                                                 if (getNextChar('L', 'l') >= 0) {
 
2032                                                                         fFillerToken = TokenName.ECHO_INVISIBLE;
 
2034                                                                 return TokenName.INLINE_HTML;
 
2037                                                         if (getNextChar('H', 'h') >= 0) {
 
2038                                                                 if (getNextChar('P', 'p') >= 0) {
 
2040                                                                         if (ignorePHPOneLiner) {
 
2041                                                                                 if (lookAheadLinePHPTag() == TokenName.INLINE_HTML) {
 
2043                                                                                         return TokenName.INLINE_HTML;
 
2047                                                                                 return TokenName.INLINE_HTML;
 
2055                                 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
 
2056                                         if (recordLineSeparator) {
 
2057                                                 pushLineSeparator();
 
2062                         } // -----------------while--------------------
 
2064                         return TokenName.INLINE_HTML;
 
2065                 } // -----------------try--------------------
 
2066                 catch (IndexOutOfBoundsException e) {
 
2067                         startPosition = start;
 
2071                 return TokenName.INLINE_HTML;
 
2075          * check if the PHP is only in this line (for CodeFormatter)
 
2079         private TokenName lookAheadLinePHPTag() {
 
2080                 int currentPositionInLine = currentPosition;
 
2081                 char previousCharInLine = ' ';
 
2082                 char currentCharInLine = ' ';
 
2083                 boolean singleQuotedStringActive = false;
 
2084                 boolean doubleQuotedStringActive = false;
 
2087                         // look ahead in this line
 
2089                                 previousCharInLine = currentCharInLine;
 
2090                                 currentCharInLine = source[currentPositionInLine++];
 
2091                                 switch (currentCharInLine) {
 
2093                                         if (previousCharInLine == '?') {
 
2094                                                 // update the scanner's current Position in the source
 
2095                                                 currentPosition = currentPositionInLine;
 
2096                                                 // use as "dummy" token
 
2097                                                 return TokenName.EOF;
 
2101                                         if (doubleQuotedStringActive) {
 
2102                                                 // ignore escaped characters in double quoted strings
 
2103                                                 previousCharInLine = currentCharInLine;
 
2104                                                 currentCharInLine = source[currentPositionInLine++];
 
2107                                         if (doubleQuotedStringActive) {
 
2108                                                 doubleQuotedStringActive = false;
 
2110                                                 if (!singleQuotedStringActive) {
 
2111                                                         doubleQuotedStringActive = true;
 
2116                                         if (singleQuotedStringActive) {
 
2117                                                 if (previousCharInLine != '\\') {
 
2118                                                         singleQuotedStringActive = false;
 
2121                                                 if (!doubleQuotedStringActive) {
 
2122                                                         singleQuotedStringActive = true;
 
2128                                         return TokenName.INLINE_HTML;
 
2130                                         if (!singleQuotedStringActive && !doubleQuotedStringActive) {
 
2132                                                 return TokenName.INLINE_HTML;
 
2136                                         if (previousCharInLine == '/' && !singleQuotedStringActive
 
2137                                                         && !doubleQuotedStringActive) {
 
2139                                                 return TokenName.INLINE_HTML;
 
2143                                         if (previousCharInLine == '/' && !singleQuotedStringActive
 
2144                                                         && !doubleQuotedStringActive) {
 
2146                                                 return TokenName.INLINE_HTML;
 
2151                 } catch (IndexOutOfBoundsException e) {
 
2153                         currentPosition = currentPositionInLine - 1;
 
2154                         return TokenName.INLINE_HTML;
 
2158         // public final void getNextUnicodeChar()
 
2159         // throws IndexOutOfBoundsException, InvalidInputException {
 
2161         // //handle the case of unicode.
 
2162         // //when a unicode appears then we must use a buffer that holds char
 
2164         // //At the end of this method currentCharacter holds the new visited char
 
2165         // //and currentPosition points right next after it
 
2167         // //ALL getNextChar.... ARE OPTIMIZED COPIES
 
2169         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
 
2170         // currentPosition++;
 
2171         // while (source[currentPosition] == 'u') {
 
2172         // currentPosition++;
 
2176         // if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
 
2178         // || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
 
2180         // || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
 
2182         // || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
 
2184         // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
 
2186         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2187         // //need the unicode buffer
 
2188         // if (withoutUnicodePtr == 0) {
 
2189         // //buffer all the entries that have been left aside....
 
2190         // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
 
2191         // System.arraycopy(
 
2194         // withoutUnicodeBuffer,
 
2196         // withoutUnicodePtr);
 
2198         // //fill the buffer with the char
 
2199         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2201         // unicodeAsBackSlash = currentCharacter == '\\';
 
2204          * Tokenize a method body, assuming that curly brackets are properly
 
2207         public final void jumpOverMethodBody() {
 
2208                 this.wasAcr = false;
 
2211                         while (true) { // loop for jumping over comments
 
2212                                 // ---------Consume white space and handles
 
2213                                 // startPosition---------
 
2214                                 boolean isWhiteSpace;
 
2216                                         startPosition = currentPosition;
 
2217                                         currentCharacter = source[currentPosition++];
 
2218                                         // if (((currentCharacter = source[currentPosition++]) ==
 
2220                                         // && (source[currentPosition] == 'u')) {
 
2221                                         // isWhiteSpace = jumpOverUnicodeWhiteSpace();
 
2223                                         if (recordLineSeparator
 
2224                                                         && ((currentCharacter == '\r') || (currentCharacter == '\n')))
 
2225                                                 pushLineSeparator();
 
2226                                         isWhiteSpace = Character.isWhitespace(currentCharacter);
 
2228                                 } while (isWhiteSpace);
 
2229                                 // -------consume token until } is found---------
 
2230                                 switch (currentCharacter) {
 
2241                                         test = getNextChar('\\');
 
2244                                                         scanDoubleQuotedEscapeCharacter();
 
2245                                                 } catch (InvalidInputException ex) {
 
2249                                                 // try { // consume next character
 
2250                                                 unicodeAsBackSlash = false;
 
2251                                                 currentCharacter = source[currentPosition++];
 
2252                                                 // if (((currentCharacter = source[currentPosition++])
 
2254                                                 // && (source[currentPosition] == 'u')) {
 
2255                                                 // getNextUnicodeChar();
 
2257                                                 if (withoutUnicodePtr != 0) {
 
2258                                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2261                                                 // } catch (InvalidInputException ex) {
 
2269                                                 // try { // consume next character
 
2270                                                 unicodeAsBackSlash = false;
 
2271                                                 currentCharacter = source[currentPosition++];
 
2272                                                 // if (((currentCharacter = source[currentPosition++])
 
2274                                                 // && (source[currentPosition] == 'u')) {
 
2275                                                 // getNextUnicodeChar();
 
2277                                                 if (withoutUnicodePtr != 0) {
 
2278                                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2281                                                 // } catch (InvalidInputException ex) {
 
2283                                                 while (currentCharacter != '"') {
 
2284                                                         if (currentCharacter == '\r') {
 
2285                                                                 if (source[currentPosition] == '\n')
 
2288                                                                 // the string cannot go further that the line
 
2290                                                         if (currentCharacter == '\n') {
 
2292                                                                 // the string cannot go further that the line
 
2294                                                         if (currentCharacter == '\\') {
 
2296                                                                         scanDoubleQuotedEscapeCharacter();
 
2297                                                                 } catch (InvalidInputException ex) {
 
2301                                                         // try { // consume next character
 
2302                                                         unicodeAsBackSlash = false;
 
2303                                                         currentCharacter = source[currentPosition++];
 
2304                                                         // if (((currentCharacter =
 
2305                                                         // source[currentPosition++]) == '\\')
 
2306                                                         // && (source[currentPosition] == 'u')) {
 
2307                                                         // getNextUnicodeChar();
 
2309                                                         if (withoutUnicodePtr != 0) {
 
2310                                                                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2313                                                         // } catch (InvalidInputException ex) {
 
2316                                         } catch (IndexOutOfBoundsException e) {
 
2322                                         if ((test = getNextChar('/', '*')) == 0) {
 
2325                                                         // get the next char
 
2326                                                         currentCharacter = source[currentPosition++];
 
2327                                                         // if (((currentCharacter =
 
2328                                                         // source[currentPosition++]) ==
 
2330                                                         // && (source[currentPosition] == 'u')) {
 
2331                                                         // //-------------unicode traitement ------------
 
2332                                                         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2333                                                         // currentPosition++;
 
2334                                                         // while (source[currentPosition] == 'u') {
 
2335                                                         // currentPosition++;
 
2338                                                         // Character.getNumericValue(source[currentPosition++]))
 
2342                                                         // Character.getNumericValue(source[currentPosition++]))
 
2346                                                         // Character.getNumericValue(source[currentPosition++]))
 
2350                                                         // Character.getNumericValue(source[currentPosition++]))
 
2353                                                         // //error don't care of the value
 
2354                                                         // currentCharacter = 'A';
 
2355                                                         // } //something different from \n and \r
 
2357                                                         // currentCharacter =
 
2358                                                         // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2361                                                         while (currentCharacter != '\r'
 
2362                                                                         && currentCharacter != '\n') {
 
2363                                                                 // get the next char
 
2364                                                                 currentCharacter = source[currentPosition++];
 
2365                                                                 // if (((currentCharacter =
 
2366                                                                 // source[currentPosition++])
 
2368                                                                 // && (source[currentPosition] == 'u')) {
 
2369                                                                 // //-------------unicode traitement
 
2371                                                                 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2372                                                                 // currentPosition++;
 
2373                                                                 // while (source[currentPosition] == 'u') {
 
2374                                                                 // currentPosition++;
 
2377                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2381                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2385                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2389                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2392                                                                 // //error don't care of the value
 
2393                                                                 // currentCharacter = 'A';
 
2394                                                                 // } //something different from \n and \r
 
2396                                                                 // currentCharacter =
 
2397                                                                 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 +
 
2402                                                         if (recordLineSeparator
 
2403                                                                         && ((currentCharacter == '\r') || (currentCharacter == '\n')))
 
2404                                                                 pushLineSeparator();
 
2405                                                 } catch (IndexOutOfBoundsException e) {
 
2406                                                 } // an eof will them be generated
 
2410                                                 // traditional and annotation comment
 
2411                                                 boolean star = false;
 
2412                                                 // try { // consume next character
 
2413                                                 unicodeAsBackSlash = false;
 
2414                                                 currentCharacter = source[currentPosition++];
 
2415                                                 // if (((currentCharacter = source[currentPosition++])
 
2417                                                 // && (source[currentPosition] == 'u')) {
 
2418                                                 // getNextUnicodeChar();
 
2420                                                 if (withoutUnicodePtr != 0) {
 
2421                                                         withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2424                                                 // } catch (InvalidInputException ex) {
 
2426                                                 if (currentCharacter == '*') {
 
2429                                                 if (recordLineSeparator
 
2430                                                                 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
 
2431                                                         pushLineSeparator();
 
2432                                                 try { // get the next char
 
2433                                                         currentCharacter = source[currentPosition++];
 
2434                                                         // if (((currentCharacter =
 
2435                                                         // source[currentPosition++]) ==
 
2437                                                         // && (source[currentPosition] == 'u')) {
 
2438                                                         // //-------------unicode traitement ------------
 
2439                                                         // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2440                                                         // currentPosition++;
 
2441                                                         // while (source[currentPosition] == 'u') {
 
2442                                                         // currentPosition++;
 
2445                                                         // Character.getNumericValue(source[currentPosition++]))
 
2449                                                         // Character.getNumericValue(source[currentPosition++]))
 
2453                                                         // Character.getNumericValue(source[currentPosition++]))
 
2457                                                         // Character.getNumericValue(source[currentPosition++]))
 
2460                                                         // //error don't care of the value
 
2461                                                         // currentCharacter = 'A';
 
2462                                                         // } //something different from * and /
 
2464                                                         // currentCharacter =
 
2465                                                         // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2468                                                         // loop until end of comment */
 
2469                                                         while ((currentCharacter != '/') || (!star)) {
 
2470                                                                 if (recordLineSeparator
 
2471                                                                                 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
 
2472                                                                         pushLineSeparator();
 
2473                                                                 star = currentCharacter == '*';
 
2475                                                                 currentCharacter = source[currentPosition++];
 
2476                                                                 // if (((currentCharacter =
 
2477                                                                 // source[currentPosition++])
 
2479                                                                 // && (source[currentPosition] == 'u')) {
 
2480                                                                 // //-------------unicode traitement
 
2482                                                                 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
 
2483                                                                 // currentPosition++;
 
2484                                                                 // while (source[currentPosition] == 'u') {
 
2485                                                                 // currentPosition++;
 
2488                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2492                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2496                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2500                                                                 // Character.getNumericValue(source[currentPosition++]))
 
2503                                                                 // //error don't care of the value
 
2504                                                                 // currentCharacter = 'A';
 
2505                                                                 // } //something different from * and /
 
2507                                                                 // currentCharacter =
 
2508                                                                 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 +
 
2513                                                 } catch (IndexOutOfBoundsException e) {
 
2521                                         if (isPHPIdentOrVarStart(currentCharacter)) {
 
2523                                                         scanIdentifierOrKeyword((currentCharacter == '$'));
 
2524                                                 } catch (InvalidInputException ex) {
 
2529                                         if (ObviousIdentCharNatures[currentCharacter] == C_DIGIT) {
 
2530                                                 // if (Character.isDigit(currentCharacter)) {
 
2533                                                 } catch (InvalidInputException ex) {
 
2540                         // -----------------end switch while try--------------------
 
2541                 } catch (IndexOutOfBoundsException e) {
 
2542                 } catch (InvalidInputException e) {
 
2547         // public final boolean jumpOverUnicodeWhiteSpace()
 
2548         // throws InvalidInputException {
 
2550         // //handle the case of unicode. Jump over the next whiteSpace
 
2551         // //making startPosition pointing on the next available char
 
2552         // //On false, the currentCharacter is filled up with a potential
 
2556         // this.wasAcr = false;
 
2557         // int c1, c2, c3, c4;
 
2558         // int unicodeSize = 6;
 
2559         // currentPosition++;
 
2560         // while (source[currentPosition] == 'u') {
 
2561         // currentPosition++;
 
2565         // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
 
2567         // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
 
2569         // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
 
2571         // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
 
2573         // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
 
2576         // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
 
2577         // if (recordLineSeparator
 
2578         // && ((currentCharacter == '\r') || (currentCharacter == '\n')))
 
2579         // pushLineSeparator();
 
2580         // if (Character.isWhitespace(currentCharacter))
 
2583         // //buffer the new char which is not a white space
 
2584         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
2585         // //withoutUnicodePtr == 1 is true here
 
2587         // } catch (IndexOutOfBoundsException e) {
 
2588         // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
 
2591         public final int[] getLineEnds() {
 
2592                 // return a bounded copy of this.lineEnds
 
2594                 System.arraycopy(lineEnds, 0, copy = new int[linePtr + 1], 0,
 
2599         public char[] getSource() {
 
2603         public static boolean isIdentifierOrKeyword (TokenName token) {
 
2604                 return (token == TokenName.IDENTIFIER) || (token.compareTo (TokenName.KEYWORD) > 0);
 
2607         final char[] optimizedCurrentTokenSource1() {
 
2608                 // return always the same char[] build only once
 
2609                 // optimization at no speed cost of 99.5 % of the singleCharIdentifier
 
2610                 char charOne = source[startPosition];
 
2665                         return new char[] { charOne };
 
2669         final char[] optimizedCurrentTokenSource2() {
 
2671                 c0 = source[startPosition];
 
2672                 c1 = source[startPosition + 1];
 
2674                         // return always the same char[] build only once
 
2675                         // optimization at no speed cost of 99.5 % of the
 
2676                         // singleCharIdentifier
 
2679                                 return charArray_va;
 
2681                                 return charArray_vb;
 
2683                                 return charArray_vc;
 
2685                                 return charArray_vd;
 
2687                                 return charArray_ve;
 
2689                                 return charArray_vf;
 
2691                                 return charArray_vg;
 
2693                                 return charArray_vh;
 
2695                                 return charArray_vi;
 
2697                                 return charArray_vj;
 
2699                                 return charArray_vk;
 
2701                                 return charArray_vl;
 
2703                                 return charArray_vm;
 
2705                                 return charArray_vn;
 
2707                                 return charArray_vo;
 
2709                                 return charArray_vp;
 
2711                                 return charArray_vq;
 
2713                                 return charArray_vr;
 
2715                                 return charArray_vs;
 
2717                                 return charArray_vt;
 
2719                                 return charArray_vu;
 
2721                                 return charArray_vv;
 
2723                                 return charArray_vw;
 
2725                                 return charArray_vx;
 
2727                                 return charArray_vy;
 
2729                                 return charArray_vz;
 
2732                 // try to return the same char[] build only once
 
2733                 int hash = ((c0 << 6) + c1) % TableSize;
 
2734                 char[][] table = charArray_length[0][hash];
 
2736                 while (++i < InternalTableSize) {
 
2737                         char[] charArray = table[i];
 
2738                         if ((c0 == charArray[0]) && (c1 == charArray[1]))
 
2741                 // ---------other side---------
 
2743                 int max = newEntry2;
 
2744                 while (++i <= max) {
 
2745                         char[] charArray = table[i];
 
2746                         if ((c0 == charArray[0]) && (c1 == charArray[1]))
 
2749                 // --------add the entry-------
 
2750                 if (++max >= InternalTableSize)
 
2753                 table[max] = (r = new char[] { c0, c1 });
 
2758         final char[] optimizedCurrentTokenSource3() {
 
2759                 // try to return the same char[] build only once
 
2761                 int hash = (((c0 = source[startPosition]) << 12)
 
2762                                 + ((c1 = source[startPosition + 1]) << 6) + (c2 = source[startPosition + 2]))
 
2764                 char[][] table = charArray_length[1][hash];
 
2766                 while (++i < InternalTableSize) {
 
2767                         char[] charArray = table[i];
 
2768                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2769                                         && (c2 == charArray[2]))
 
2772                 // ---------other side---------
 
2774                 int max = newEntry3;
 
2775                 while (++i <= max) {
 
2776                         char[] charArray = table[i];
 
2777                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2778                                         && (c2 == charArray[2]))
 
2781                 // --------add the entry-------
 
2782                 if (++max >= InternalTableSize)
 
2785                 table[max] = (r = new char[] { c0, c1, c2 });
 
2790         final char[] optimizedCurrentTokenSource4() {
 
2791                 // try to return the same char[] build only once
 
2792                 char c0, c1, c2, c3;
 
2793                 long hash = ((((long) (c0 = source[startPosition])) << 18)
 
2794                                 + ((c1 = source[startPosition + 1]) << 12)
 
2795                                 + ((c2 = source[startPosition + 2]) << 6) + (c3 = source[startPosition + 3]))
 
2797                 char[][] table = charArray_length[2][(int) hash];
 
2799                 while (++i < InternalTableSize) {
 
2800                         char[] charArray = table[i];
 
2801                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2802                                         && (c2 == charArray[2]) && (c3 == charArray[3]))
 
2805                 // ---------other side---------
 
2808                 int max = newEntry4;
 
2809                 while (++i <= max) {
 
2810                         char[] charArray = table[i];
 
2811                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2812                                         && (c2 == charArray[2]) && (c3 == charArray[3]))
 
2815                 // --------add the entry-------
 
2816                 if (++max >= InternalTableSize)
 
2819                 table[max] = (r = new char[] { c0, c1, c2, c3 });
 
2824         final char[] optimizedCurrentTokenSource5() {
 
2825                 // try to return the same char[] build only once
 
2826                 char c0, c1, c2, c3, c4;
 
2827                 long hash = ((((long) (c0 = source[startPosition])) << 24)
 
2828                                 + (((long) (c1 = source[startPosition + 1])) << 18)
 
2829                                 + ((c2 = source[startPosition + 2]) << 12)
 
2830                                 + ((c3 = source[startPosition + 3]) << 6) + (c4 = source[startPosition + 4]))
 
2832                 char[][] table = charArray_length[3][(int) hash];
 
2834                 while (++i < InternalTableSize) {
 
2835                         char[] charArray = table[i];
 
2836                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2837                                         && (c2 == charArray[2]) && (c3 == charArray[3])
 
2838                                         && (c4 == charArray[4]))
 
2841                 // ---------other side---------
 
2843                 int max = newEntry5;
 
2844                 while (++i <= max) {
 
2845                         char[] charArray = table[i];
 
2846                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2847                                         && (c2 == charArray[2]) && (c3 == charArray[3])
 
2848                                         && (c4 == charArray[4]))
 
2851                 // --------add the entry-------
 
2852                 if (++max >= InternalTableSize)
 
2855                 table[max] = (r = new char[] { c0, c1, c2, c3, c4 });
 
2860         final char[] optimizedCurrentTokenSource6() {
 
2861                 // try to return the same char[] build only once
 
2862                 char c0, c1, c2, c3, c4, c5;
 
2863                 long hash = ((((long) (c0 = source[startPosition])) << 32)
 
2864                                 + (((long) (c1 = source[startPosition + 1])) << 24)
 
2865                                 + (((long) (c2 = source[startPosition + 2])) << 18)
 
2866                                 + ((c3 = source[startPosition + 3]) << 12)
 
2867                                 + ((c4 = source[startPosition + 4]) << 6) + (c5 = source[startPosition + 5]))
 
2869                 char[][] table = charArray_length[4][(int) hash];
 
2871                 while (++i < InternalTableSize) {
 
2872                         char[] charArray = table[i];
 
2873                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2874                                         && (c2 == charArray[2]) && (c3 == charArray[3])
 
2875                                         && (c4 == charArray[4]) && (c5 == charArray[5]))
 
2878                 // ---------other side---------
 
2880                 int max = newEntry6;
 
2881                 while (++i <= max) {
 
2882                         char[] charArray = table[i];
 
2883                         if ((c0 == charArray[0]) && (c1 == charArray[1])
 
2884                                         && (c2 == charArray[2]) && (c3 == charArray[3])
 
2885                                         && (c4 == charArray[4]) && (c5 == charArray[5]))
 
2888                 // --------add the entry-------
 
2889                 if (++max >= InternalTableSize)
 
2892                 table[max] = (r = new char[] { c0, c1, c2, c3, c4, c5 });
 
2897         public final void pushLineSeparator() throws InvalidInputException {
 
2898                 // see comment on isLineDelimiter(char) for the use of '\n' and '\r'
 
2899                 final int INCREMENT = 250;
 
2900                 if (this.checkNonExternalizedStringLiterals) {
 
2901                         // reinitialize the current line for non externalize strings purpose
 
2904                 // currentCharacter is at position currentPosition-1
 
2906                 if (currentCharacter == '\r') {
 
2907                         int separatorPos = currentPosition - 1;
 
2908                         if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
 
2910                         // System.out.println("CR-" + separatorPos);
 
2912                                 lineEnds[++linePtr] = separatorPos;
 
2913                         } catch (IndexOutOfBoundsException e) {
 
2914                                 // linePtr value is correct
 
2915                                 int oldLength = lineEnds.length;
 
2916                                 int[] old = lineEnds;
 
2917                                 lineEnds = new int[oldLength + INCREMENT];
 
2918                                 System.arraycopy(old, 0, lineEnds, 0, oldLength);
 
2919                                 lineEnds[linePtr] = separatorPos;
 
2921                         // look-ahead for merged cr+lf
 
2923                                 if (source[currentPosition] == '\n') {
 
2924                                         // System.out.println("look-ahead LF-" + currentPosition);
 
2925                                         lineEnds[linePtr] = currentPosition;
 
2931                         } catch (IndexOutOfBoundsException e) {
 
2936                         if (currentCharacter == '\n') {
 
2937                                 // must merge eventual cr followed by lf
 
2938                                 if (wasAcr && (lineEnds[linePtr] == (currentPosition - 2))) {
 
2939                                         // System.out.println("merge LF-" + (currentPosition - 1));
 
2940                                         lineEnds[linePtr] = currentPosition - 1;
 
2942                                         int separatorPos = currentPosition - 1;
 
2943                                         if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
 
2945                                         // System.out.println("LF-" + separatorPos);
 
2947                                                 lineEnds[++linePtr] = separatorPos;
 
2948                                         } catch (IndexOutOfBoundsException e) {
 
2949                                                 // linePtr value is correct
 
2950                                                 int oldLength = lineEnds.length;
 
2951                                                 int[] old = lineEnds;
 
2952                                                 lineEnds = new int[oldLength + INCREMENT];
 
2953                                                 System.arraycopy(old, 0, lineEnds, 0, oldLength);
 
2954                                                 lineEnds[linePtr] = separatorPos;
 
2962         public final void pushUnicodeLineSeparator() {
 
2963                 // isUnicode means that the \r or \n has been read as a unicode
 
2965                 // see comment on isLineDelimiter(char) for the use of '\n' and '\r'
 
2966                 final int INCREMENT = 250;
 
2967                 // currentCharacter is at position currentPosition-1
 
2968                 if (this.checkNonExternalizedStringLiterals) {
 
2969                         // reinitialize the current line for non externalize strings purpose
 
2973                 if (currentCharacter == '\r') {
 
2974                         int separatorPos = currentPosition - 6;
 
2975                         if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
 
2977                         // System.out.println("CR-" + separatorPos);
 
2979                                 lineEnds[++linePtr] = separatorPos;
 
2980                         } catch (IndexOutOfBoundsException e) {
 
2981                                 // linePtr value is correct
 
2982                                 int oldLength = lineEnds.length;
 
2983                                 int[] old = lineEnds;
 
2984                                 lineEnds = new int[oldLength + INCREMENT];
 
2985                                 System.arraycopy(old, 0, lineEnds, 0, oldLength);
 
2986                                 lineEnds[linePtr] = separatorPos;
 
2988                         // look-ahead for merged cr+lf
 
2989                         if (source[currentPosition] == '\n') {
 
2990                                 // System.out.println("look-ahead LF-" + currentPosition);
 
2991                                 lineEnds[linePtr] = currentPosition;
 
2999                         if (currentCharacter == '\n') {
 
3000                                 // must merge eventual cr followed by lf
 
3001                                 if (wasAcr && (lineEnds[linePtr] == (currentPosition - 7))) {
 
3002                                         // System.out.println("merge LF-" + (currentPosition - 1));
 
3003                                         lineEnds[linePtr] = currentPosition - 6;
 
3005                                         int separatorPos = currentPosition - 6;
 
3006                                         if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
 
3008                                         // System.out.println("LF-" + separatorPos);
 
3010                                                 lineEnds[++linePtr] = separatorPos;
 
3011                                         } catch (IndexOutOfBoundsException e) {
 
3012                                                 // linePtr value is correct
 
3013                                                 int oldLength = lineEnds.length;
 
3014                                                 int[] old = lineEnds;
 
3015                                                 lineEnds = new int[oldLength + INCREMENT];
 
3016                                                 System.arraycopy(old, 0, lineEnds, 0, oldLength);
 
3017                                                 lineEnds[linePtr] = separatorPos;
 
3025         public void recordComment(TokenName token) {
 
3027                 int stopPosition = this.currentPosition;
 
3030                         stopPosition = -this.lastCommentLinePosition;
 
3033                         stopPosition = -this.currentPosition;
 
3037                 // a new comment is recorded
 
3038                 int length = this.commentStops.length;
 
3039                 if (++this.commentPtr >= length) {
 
3040                         System.arraycopy(this.commentStops, 0,
 
3041                                         this.commentStops = new int[length + 30], 0, length);
 
3042                         // grows the positions buffers too
 
3043                         System.arraycopy(this.commentStarts, 0,
 
3044                                         this.commentStarts = new int[length + 30], 0, length);
 
3046                 this.commentStops[this.commentPtr] = stopPosition;
 
3047                 this.commentStarts[this.commentPtr] = this.startPosition;
 
3050         // public final void recordComment(boolean isJavadoc) {
 
3051         // // a new annotation comment is recorded
 
3053         // commentStops[++commentPtr] = isJavadoc
 
3054         // ? currentPosition
 
3055         // : -currentPosition;
 
3056         // } catch (IndexOutOfBoundsException e) {
 
3057         // int oldStackLength = commentStops.length;
 
3058         // int[] oldStack = commentStops;
 
3059         // commentStops = new int[oldStackLength + 30];
 
3060         // System.arraycopy(oldStack, 0, commentStops, 0, oldStackLength);
 
3061         // commentStops[commentPtr] = isJavadoc ? currentPosition :
 
3062         // -currentPosition;
 
3063         // //grows the positions buffers too
 
3064         // int[] old = commentStarts;
 
3065         // commentStarts = new int[oldStackLength + 30];
 
3066         // System.arraycopy(old, 0, commentStarts, 0, oldStackLength);
 
3068         // //the buffer is of a correct size here
 
3069         // commentStarts[commentPtr] = startPosition;
 
3071         public void resetTo(int begin, int end) {
 
3072                 // reset the scanner to a given position where it may rescan again
 
3074                 initialPosition = startPosition = currentPosition = begin;
 
3075                 eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
 
3076                 commentPtr = -1; // reset comment stack
 
3079         public final void scanSingleQuotedEscapeCharacter()
 
3080                         throws InvalidInputException {
 
3081                 // the string with "\\u" is a legal string of two chars \ and u
 
3082                 // thus we use a direct access to the source (for regular cases).
 
3083                 // if (unicodeAsBackSlash) {
 
3084                 // // consume next character
 
3085                 // unicodeAsBackSlash = false;
 
3086                 // if (((currentCharacter = source[currentPosition++]) == '\\')
 
3087                 // && (source[currentPosition] == 'u')) {
 
3088                 // getNextUnicodeChar();
 
3090                 // if (withoutUnicodePtr != 0) {
 
3091                 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
3095                 currentCharacter = source[currentPosition++];
 
3096                 switch (currentCharacter) {
 
3098                         currentCharacter = '\'';
 
3101                         currentCharacter = '\\';
 
3104                         currentCharacter = '\\';
 
3109         public final void scanDoubleQuotedEscapeCharacter()
 
3110                         throws InvalidInputException {
 
3111                 currentCharacter = source[currentPosition++];
 
3112                 switch (currentCharacter) {
 
3114                 // currentCharacter = '\b';
 
3117                         currentCharacter = '\t';
 
3120                         currentCharacter = '\n';
 
3123                 // currentCharacter = '\f';
 
3126                         currentCharacter = '\r';
 
3129                         currentCharacter = '\"';
 
3132                         currentCharacter = '\'';
 
3135                         currentCharacter = '\\';
 
3138                         currentCharacter = '$';
 
3141                         // -----------octal escape--------------
 
3143                         // OctalDigit OctalDigit
 
3144                         // ZeroToThree OctalDigit OctalDigit
 
3145                         int number = Character.getNumericValue(currentCharacter);
 
3146                         if (number >= 0 && number <= 7) {
 
3147                                 boolean zeroToThreeNot = number > 3;
 
3149                                                 .isDigit(currentCharacter = source[currentPosition++])) {
 
3150                                         int digit = Character.getNumericValue(currentCharacter);
 
3151                                         if (digit >= 0 && digit <= 7) {
 
3152                                                 number = (number * 8) + digit;
 
3154                                                                 .isDigit(currentCharacter = source[currentPosition++])) {
 
3155                                                         if (zeroToThreeNot) { // has read \NotZeroToThree
 
3157                                                                 // Digit --> ignore last character
 
3161                                                                                 .getNumericValue(currentCharacter);
 
3162                                                                 if (digit >= 0 && digit <= 7) {
 
3163                                                                         // has read \ZeroToThree OctalDigit
 
3165                                                                         number = (number * 8) + digit;
 
3166                                                                 } else { // has read \ZeroToThree OctalDigit
 
3168                                                                         // --> ignore last character
 
3172                                                 } else { // has read \OctalDigit NonDigit--> ignore
 
3177                                         } else { // has read \OctalDigit NonOctalDigit--> ignore
 
3182                                 } else { // has read \OctalDigit --> ignore last character
 
3186                                         throw new InvalidInputException(INVALID_ESCAPE);
 
3187                                 currentCharacter = (char) number;
 
3190                         // throw new InvalidInputException(INVALID_ESCAPE);
 
3194         // public int scanIdentifierOrKeyword() throws InvalidInputException {
 
3195         // return scanIdentifierOrKeyword( false );
 
3197         public TokenName scanIdentifierOrKeyword(boolean isVariable)
 
3198                         throws InvalidInputException {
 
3200                 // first dispatch on the first char.
 
3201                 // then the length. If there are several
 
3202                 // keywords with the same length AND the same first char, then do another
 
3203                 // disptach on the second char :-)...cool....but fast !
 
3204                 useAssertAsAnIndentifier = false;
 
3205                 while (getNextCharAsJavaIdentifierPart()) {
 
3209                         // if (new String(getCurrentTokenSource()).equals("$this")) {
 
3210                         // return TokenName.this;
 
3212                         return TokenName.VARIABLE;
 
3217                 // if (withoutUnicodePtr == 0)
 
3218                 // quick test on length == 1 but not on length > 12 while most
 
3220                 // have a length which is <= 12...but there are lots of identifier with
 
3221                 // only one char....
 
3223                 if ((length = currentPosition - startPosition) == 1)
 
3224                         return TokenName.IDENTIFIER;
 
3226                 data = new char[length];
 
3227                 index = startPosition;
 
3228                 for (int i = 0; i < length; i++) {
 
3229                         data[i] = Character.toLowerCase(source[index + i]);
 
3233                 // if ((length = withoutUnicodePtr) == 1)
 
3234                 // return TokenName.Identifier;
 
3235                 // // data = withoutUnicodeBuffer;
 
3236                 // data = new char[withoutUnicodeBuffer.length];
 
3237                 // for (int i = 0; i < withoutUnicodeBuffer.length; i++) {
 
3238                 // data[i] = Character.toLowerCase(withoutUnicodeBuffer[i]);
 
3242                 firstLetter = data[index];
 
3243                 switch (firstLetter) {
 
3248                                 if ((data[++index] == '_') && (data[++index] == 'f')
 
3249                                                 && (data[++index] == 'i') && (data[++index] == 'l')
 
3250                                                 && (data[++index] == 'e') && (data[++index] == '_')
 
3251                                                 && (data[++index] == '_'))
 
3252                                         return TokenName.FILE;
 
3253                                 index = 0; // __LINE__
 
3254                                 if ((data[++index] == '_') && (data[++index] == 'l')
 
3255                                                 && (data[++index] == 'i') && (data[++index] == 'n')
 
3256                                                 && (data[++index] == 'e') && (data[++index] == '_')
 
3257                                                 && (data[++index] == '_'))
 
3258                                         return TokenName.LINE;
 
3262                                 if ((data[++index] == '_') && (data[++index] == 'c')
 
3263                                                 && (data[++index] == 'l') && (data[++index] == 'a')
 
3264                                                 && (data[++index] == 's') && (data[++index] == 's')
 
3265                                                 && (data[++index] == '_') && (data[++index] == '_'))
 
3266                                         return TokenName.CLASS_C;
 
3270                                 if ((data[++index] == '_') && (data[++index] == 'm')
 
3271                                                 && (data[++index] == 'e') && (data[++index] == 't')
 
3272                                                 && (data[++index] == 'h') && (data[++index] == 'o')
 
3273                                                 && (data[++index] == 'd') && (data[++index] == '_')
 
3274                                                 && (data[++index] == '_'))
 
3275                                         return TokenName.METHOD_C;
 
3279                                 if ((data[++index] == '_') && (data[++index] == 'f')
 
3280                                                 && (data[++index] == 'u') && (data[++index] == 'n')
 
3281                                                 && (data[++index] == 'c') && (data[++index] == 't')
 
3282                                                 && (data[++index] == 'i') && (data[++index] == 'o')
 
3283                                                 && (data[++index] == 'n') && (data[++index] == '_')
 
3284                                                 && (data[++index] == '_'))
 
3285                                         return TokenName.FUNC_C;
 
3288                         return TokenName.IDENTIFIER;
 
3290                         // as and array abstract
 
3294                                 if ((data[++index] == 's')) {
 
3295                                         return TokenName.AS;
 
3297                                 return TokenName.IDENTIFIER;
 
3300                                 if ((data[++index] == 'n') && (data[++index] == 'd')) {
 
3301                                         return TokenName.OP_AND_OLD;
 
3303                                 return TokenName.IDENTIFIER;
 
3306                                 if ((data[++index] == 'r') && (data[++index] == 'r')
 
3307                                                 && (data[++index] == 'a') && (data[++index] == 'y'))
 
3308                                         return TokenName.ARRAY;
 
3309                                 return TokenName.IDENTIFIER;
 
3311                                 if ((data[++index] == 'b') && (data[++index] == 's')
 
3312                                                 && (data[++index] == 't') && (data[++index] == 'r')
 
3313                                                 && (data[++index] == 'a') && (data[++index] == 'c')
 
3314                                                 && (data[++index] == 't'))
 
3315                                         return TokenName.ABSTRACT;
 
3316                                 return TokenName.IDENTIFIER;
 
3318                         return TokenName.IDENTIFIER;
 
3323                                 if ((data[++index] == 'r') && (data[++index] == 'e')
 
3324                                                 && (data[++index] == 'a') && (data[++index] == 'k'))
 
3325                                         return TokenName.BREAK;
 
3326                                 return TokenName.IDENTIFIER;
 
3328                         return TokenName.IDENTIFIER;
 
3330                         // case catch class clone const continue
 
3333                                 if ((data[++index] == 'a') && (data[++index] == 's')
 
3334                                                 && (data[++index] == 'e'))
 
3335                                         return TokenName.CASE;
 
3336                                 return TokenName.IDENTIFIER;
 
3338                                 if ((data[++index] == 'a') && (data[++index] == 't')
 
3339                                                 && (data[++index] == 'c') && (data[++index] == 'h'))
 
3340                                         return TokenName.CATCH;
 
3342                                 if ((data[++index] == 'l') && (data[++index] == 'a')
 
3343                                                 && (data[++index] == 's') && (data[++index] == 's'))
 
3344                                         return TokenName.CLASS;
 
3346                                 if ((data[++index] == 'l') && (data[++index] == 'o')
 
3347                                                 && (data[++index] == 'n') && (data[++index] == 'e'))
 
3348                                         return TokenName.CLONE;
 
3350                                 if ((data[++index] == 'o') && (data[++index] == 'n')
 
3351                                                 && (data[++index] == 's') && (data[++index] == 't'))
 
3352                                         return TokenName.CONST;
 
3353                                 return TokenName.IDENTIFIER;
 
3355                                 if ((data[++index] == 'o') && (data[++index] == 'n')
 
3356                                                 && (data[++index] == 't') && (data[++index] == 'i')
 
3357                                                 && (data[++index] == 'n') && (data[++index] == 'u')
 
3358                                                 && (data[++index] == 'e'))
 
3359                                         return TokenName.CONTINUE;
 
3360                                 return TokenName.IDENTIFIER;
 
3362                         return TokenName.IDENTIFIER;
 
3364                         // declare default do die
 
3365                         // TODO delete define ==> no keyword !
 
3368                                 if ((data[++index] == 'o'))
 
3369                                         return TokenName.DO;
 
3370                                 return TokenName.IDENTIFIER;
 
3372                                 // if ((data[++index] == 'e')
 
3373                                 // && (data[++index] == 'f')
 
3374                                 // && (data[++index] == 'i')
 
3375                                 // && (data[++index] == 'n')
 
3376                                 // && (data[++index] == 'e'))
 
3377                                 // return TokenName.define;
 
3379                                 // return TokenName.Identifier;
 
3381                                 if ((data[++index] == 'e') && (data[++index] == 'c')
 
3382                                                 && (data[++index] == 'l') && (data[++index] == 'a')
 
3383                                                 && (data[++index] == 'r') && (data[++index] == 'e'))
 
3384                                         return TokenName.DECLARE;
 
3386                                 if ((data[++index] == 'e') && (data[++index] == 'f')
 
3387                                                 && (data[++index] == 'a') && (data[++index] == 'u')
 
3388                                                 && (data[++index] == 'l') && (data[++index] == 't'))
 
3389                                         return TokenName.DEFAULT;
 
3390                                 return TokenName.IDENTIFIER;
 
3392                         return TokenName.IDENTIFIER;
 
3394                         // echo else exit elseif extends eval
 
3397                                 if ((data[++index] == 'c') && (data[++index] == 'h')
 
3398                                                 && (data[++index] == 'o'))
 
3399                                         return TokenName.ECHO;
 
3400                                 else if ((data[index] == 'l') && (data[++index] == 's')
 
3401                                                 && (data[++index] == 'e'))
 
3402                                         return TokenName.ELSE;
 
3403                                 else if ((data[index] == 'x') && (data[++index] == 'i')
 
3404                                                 && (data[++index] == 't'))
 
3405                                         return TokenName.EXIT;
 
3406                                 else if ((data[index] == 'v') && (data[++index] == 'a')
 
3407                                                 && (data[++index] == 'l'))
 
3408                                         return TokenName.EVAL;
 
3409                                 return TokenName.IDENTIFIER;
 
3412                                 if ((data[++index] == 'n') && (data[++index] == 'd')
 
3413                                                 && (data[++index] == 'i') && (data[++index] == 'f'))
 
3414                                         return TokenName.ENDIF;
 
3415                                 if ((data[index] == 'm') && (data[++index] == 'p')
 
3416                                                 && (data[++index] == 't') && (data[++index] == 'y'))
 
3417                                         return TokenName.EMPTY;
 
3418                                 return TokenName.IDENTIFIER;
 
3421                                 if ((data[++index] == 'n') && (data[++index] == 'd')
 
3422                                                 && (data[++index] == 'f') && (data[++index] == 'o')
 
3423                                                 && (data[++index] == 'r'))
 
3424                                         return TokenName.ENDFOR;
 
3425                                 else if ((data[index] == 'l') && (data[++index] == 's')
 
3426                                                 && (data[++index] == 'e') && (data[++index] == 'i')
 
3427                                                 && (data[++index] == 'f'))
 
3428                                         return TokenName.ELSEIF;
 
3429                                 return TokenName.IDENTIFIER;
 
3431                                 if ((data[++index] == 'x') && (data[++index] == 't')
 
3432                                                 && (data[++index] == 'e') && (data[++index] == 'n')
 
3433                                                 && (data[++index] == 'd') && (data[++index] == 's'))
 
3434                                         return TokenName.EXTENDS;
 
3435                                 return TokenName.IDENTIFIER;
 
3438                                 if ((data[++index] == 'n') && (data[++index] == 'd')
 
3439                                                 && (data[++index] == 'w') && (data[++index] == 'h')
 
3440                                                 && (data[++index] == 'i') && (data[++index] == 'l')
 
3441                                                 && (data[++index] == 'e'))
 
3442                                         return TokenName.ENDWHILE;
 
3443                                 return TokenName.IDENTIFIER;
 
3446                                 if ((data[++index] == 'n') && (data[++index] == 'd')
 
3447                                                 && (data[++index] == 's') && (data[++index] == 'w')
 
3448                                                 && (data[++index] == 'i') && (data[++index] == 't')
 
3449                                                 && (data[++index] == 'c') && (data[++index] == 'h'))
 
3450                                         return TokenName.ENDSWITCH;
 
3451                                 return TokenName.IDENTIFIER;
 
3454                                 if ((data[++index] == 'n') && (data[++index] == 'd')
 
3455                                                 && (data[++index] == 'd') && (data[++index] == 'e')
 
3456                                                 && (data[++index] == 'c') && (data[++index] == 'l')
 
3457                                                 && (data[++index] == 'a') && (data[++index] == 'r')
 
3458                                                 && (data[++index] == 'e'))
 
3459                                         return TokenName.ENDDECLARE;
 
3461                                 if ((data[++index] == 'n') // endforeach
 
3462                                                 && (data[++index] == 'd')
 
3463                                                 && (data[++index] == 'f')
 
3464                                                 && (data[++index] == 'o')
 
3465                                                 && (data[++index] == 'r')
 
3466                                                 && (data[++index] == 'e')
 
3467                                                 && (data[++index] == 'a')
 
3468                                                 && (data[++index] == 'c') && (data[++index] == 'h'))
 
3469                                         return TokenName.ENDFOREACH;
 
3470                                 return TokenName.IDENTIFIER;
 
3472                         return TokenName.IDENTIFIER;
 
3474                         // for false final function
 
3477                                 if ((data[++index] == 'o') && (data[++index] == 'r'))
 
3478                                         return TokenName.FOR;
 
3479                                 return TokenName.IDENTIFIER;
 
3481                                 // if ((data[++index] == 'a') && (data[++index] == 'l')
 
3482                                 // && (data[++index] == 's') && (data[++index] == 'e'))
 
3483                                 // return TokenName.false;
 
3484                                 if ((data[++index] == 'i') && (data[++index] == 'n')
 
3485                                                 && (data[++index] == 'a') && (data[++index] == 'l'))
 
3486                                         return TokenName.FINAL;
 
3487                                 return TokenName.IDENTIFIER;
 
3490                                 if ((data[++index] == 'o') && (data[++index] == 'r')
 
3491                                                 && (data[++index] == 'e') && (data[++index] == 'a')
 
3492                                                 && (data[++index] == 'c') && (data[++index] == 'h'))
 
3493                                         return TokenName.FOREACH;
 
3494                                 return TokenName.IDENTIFIER;
 
3497                                 if ((data[++index] == 'u') && (data[++index] == 'n')
 
3498                                                 && (data[++index] == 'c') && (data[++index] == 't')
 
3499                                                 && (data[++index] == 'i') && (data[++index] == 'o')
 
3500                                                 && (data[++index] == 'n'))
 
3501                                         return TokenName.FUNCTION;
 
3502                                 return TokenName.IDENTIFIER;
 
3504                         return TokenName.IDENTIFIER;
 
3508                                 if ((data[++index] == 'l') && (data[++index] == 'o')
 
3509                                                 && (data[++index] == 'b') && (data[++index] == 'a')
 
3510                                                 && (data[++index] == 'l')) {
 
3511                                         return TokenName.GLOBAL;
 
3514                         else if (length == 4) {  // goto
 
3515                 if ((data[++index] == 'o') && 
 
3516                     (data[++index] == 't') && 
 
3517                     (data[++index] == 'o')) {
 
3518                     return TokenName.GOTO;
 
3521                         return TokenName.IDENTIFIER;
 
3523                         // if int isset include include_once instanceof interface implements
 
3526                                 if (data[++index] == 'f')
 
3527                                         return TokenName.IF;
 
3528                                 return TokenName.IDENTIFIER;
 
3530                                 // if ((data[++index] == 'n') && (data[++index] == 't'))
 
3531                                 // return TokenName.int;
 
3533                                 // return TokenName.IDENTIFIER;
 
3535                                 if ((data[++index] == 's') && (data[++index] == 's')
 
3536                                                 && (data[++index] == 'e') && (data[++index] == 't'))
 
3537                                         return TokenName.ISSET;
 
3538                                 return TokenName.IDENTIFIER;
 
3540                                 if ((data[++index] == 'n') && (data[++index] == 'c')
 
3541                                                 && (data[++index] == 'l') && (data[++index] == 'u')
 
3542                                                 && (data[++index] == 'd') && (data[++index] == 'e'))
 
3543                                         return TokenName.INCLUDE;
 
3544                                 return TokenName.IDENTIFIER;
 
3547                                 if ((data[++index] == 'n') && (data[++index] == 't')
 
3548                                                 && (data[++index] == 'e') && (data[++index] == 'r')
 
3549                                                 && (data[++index] == 'f') && (data[++index] == 'a')
 
3550                                                 && (data[++index] == 'c') && (data[++index] == 'e'))
 
3551                                         return TokenName.INTERFACE;
 
3552                                 return TokenName.IDENTIFIER;
 
3554                                 // instanceof implements
 
3555                                 if ((data[++index] == 'n') && (data[++index] == 's')
 
3556                                                 && (data[++index] == 't') && (data[++index] == 'a')
 
3557                                                 && (data[++index] == 'n') && (data[++index] == 'c')
 
3558                                                 && (data[++index] == 'e') && (data[++index] == 'o')
 
3559                                                 && (data[++index] == 'f'))
 
3560                                         return TokenName.INSTANCEOF;
 
3561                                 if ((data[index] == 'm') && (data[++index] == 'p')
 
3562                                                 && (data[++index] == 'l') && (data[++index] == 'e')
 
3563                                                 && (data[++index] == 'm') && (data[++index] == 'e')
 
3564                                                 && (data[++index] == 'n') && (data[++index] == 't')
 
3565                                                 && (data[++index] == 's'))
 
3566                                         return TokenName.IMPLEMENTS;
 
3567                                 return TokenName.IDENTIFIER;
 
3568                         case 12: // include_once
 
3569                                 if ((data[++index] == 'n') && (data[++index] == 'c')
 
3570                                                 && (data[++index] == 'l') && (data[++index] == 'u')
 
3571                                                 && (data[++index] == 'd') && (data[++index] == 'e')
 
3572                                                 && (data[++index] == '_') && (data[++index] == 'o')
 
3573                                                 && (data[++index] == 'n') && (data[++index] == 'c')
 
3574                                                 && (data[++index] == 'e'))
 
3575                                         return TokenName.INCLUDE_ONCE;
 
3576                                 return TokenName.IDENTIFIER;
 
3578                         return TokenName.IDENTIFIER;
 
3582                                 if ((data[++index] == 'i') && (data[++index] == 's')
 
3583                                                 && (data[++index] == 't')) {
 
3584                                         return TokenName.LIST;
 
3587                         return TokenName.IDENTIFIER;
 
3589                         // new null namespace
 
3592                                 if ((data[++index] == 'e') && (data[++index] == 'w'))
 
3593                                         return TokenName.NEW;
 
3594                                 return TokenName.IDENTIFIER;
 
3596                                 // if ((data[++index] == 'u') && (data[++index] == 'l')
 
3597                                 // && (data[++index] == 'l'))
 
3598                                 // return TokenName.null;
 
3600                                 // return TokenName.IDENTIFIER;
 
3602                 if ((data[++index] == 'a') && (data[++index] == 'm')
 
3603                         && (data[++index] == 'e') && (data[++index] == 's')
 
3604                         && (data[++index] == 'p') && (data[++index] == 'a')
 
3605                         && (data[++index] == 'c') && (data[++index] == 'e')) {
 
3606                     return TokenName.NAMESPACE;
 
3608                             return TokenName.IDENTIFIER;
 
3610                         return TokenName.IDENTIFIER;
 
3614                                 if (data[++index] == 'r') {
 
3615                                         return TokenName.OP_OR_OLD;
 
3618                         // if (length == 12) {
 
3619                         // if ((data[++index] == 'l')
 
3620                         // && (data[++index] == 'd')
 
3621                         // && (data[++index] == '_')
 
3622                         // && (data[++index] == 'f')
 
3623                         // && (data[++index] == 'u')
 
3624                         // && (data[++index] == 'n')
 
3625                         // && (data[++index] == 'c')
 
3626                         // && (data[++index] == 't')
 
3627                         // && (data[++index] == 'i')
 
3628                         // && (data[++index] == 'o')
 
3629                         // && (data[++index] == 'n')) {
 
3630                         // return TokenName.old_function;
 
3633                         return TokenName.IDENTIFIER;
 
3635                         // print public private protected
 
3638                                 if ((data[++index] == 'r') && (data[++index] == 'i')
 
3639                                                 && (data[++index] == 'n') && (data[++index] == 't')) {
 
3640                                         return TokenName.PRINT;
 
3642                                 return TokenName.IDENTIFIER;
 
3644                                 if ((data[++index] == 'u') && (data[++index] == 'b')
 
3645                                                 && (data[++index] == 'l') && (data[++index] == 'i')
 
3646                                                 && (data[++index] == 'c')) {
 
3647                                         return TokenName.PUBLIC;
 
3649                                 return TokenName.IDENTIFIER;
 
3651                                 if ((data[++index] == 'r') && (data[++index] == 'i')
 
3652                                                 && (data[++index] == 'v') && (data[++index] == 'a')
 
3653                                                 && (data[++index] == 't') && (data[++index] == 'e')) {
 
3654                                         return TokenName.PRIVATE;
 
3656                                 return TokenName.IDENTIFIER;
 
3658                                 if ((data[++index] == 'r') && (data[++index] == 'o')
 
3659                                                 && (data[++index] == 't') && (data[++index] == 'e')
 
3660                                                 && (data[++index] == 'c') && (data[++index] == 't')
 
3661                                                 && (data[++index] == 'e') && (data[++index] == 'd')) {
 
3662                                         return TokenName.PROTECTED;
 
3664                                 return TokenName.IDENTIFIER;
 
3666                         return TokenName.IDENTIFIER;
 
3668                         // return require require_once
 
3670                                 if ((data[++index] == 'e') && (data[++index] == 't')
 
3671                                                 && (data[++index] == 'u') && (data[++index] == 'r')
 
3672                                                 && (data[++index] == 'n')) {
 
3673                                         return TokenName.RETURN;
 
3675                         } else if (length == 7) {
 
3676                                 if ((data[++index] == 'e') && (data[++index] == 'q')
 
3677                                                 && (data[++index] == 'u') && (data[++index] == 'i')
 
3678                                                 && (data[++index] == 'r') && (data[++index] == 'e')) {
 
3679                                         return TokenName.REQUIRE;
 
3681                         } else if (length == 12) {
 
3682                                 if ((data[++index] == 'e') && (data[++index] == 'q')
 
3683                                                 && (data[++index] == 'u') && (data[++index] == 'i')
 
3684                                                 && (data[++index] == 'r') && (data[++index] == 'e')
 
3685                                                 && (data[++index] == '_') && (data[++index] == 'o')
 
3686                                                 && (data[++index] == 'n') && (data[++index] == 'c')
 
3687                                                 && (data[++index] == 'e')) {
 
3688                                         return TokenName.REQUIRE_ONCE;
 
3691                         return TokenName.IDENTIFIER;
 
3693                         // self static switch
 
3696                         // if ((data[++index] == 'e') && (data[++index] == 'l') &&
 
3699                         // return TokenName.self;
 
3701                         // return TokenName.IDENTIFIER;
 
3703                                 if (data[++index] == 't')
 
3704                                         if ((data[++index] == 'a') && (data[++index] == 't')
 
3705                                                         && (data[++index] == 'i') && (data[++index] == 'c')) {
 
3706                                                 return TokenName.STATIC;
 
3708                                                 return TokenName.IDENTIFIER;
 
3709                                 else if ((data[index] == 'w') && (data[++index] == 'i')
 
3710                                                 && (data[++index] == 't') && (data[++index] == 'c')
 
3711                                                 && (data[++index] == 'h'))
 
3712                                         return TokenName.SWITCH;
 
3714                         return TokenName.IDENTIFIER;
 
3719                                 if ((data[++index] == 'r') && (data[++index] == 'y'))
 
3720                                         return TokenName.TRY;
 
3722                                 // if ((data[++index] == 'r') && (data[++index] == 'u')
 
3723                                 // && (data[++index] == 'e'))
 
3724                                 // return TokenName.true;
 
3726                                          return TokenName.IDENTIFIER;
 
3728                                 if ((data[++index] == 'h') && (data[++index] == 'r')
 
3729                                                 && (data[++index] == 'o') && (data[++index] == 'w'))
 
3730                                         return TokenName.THROW;
 
3732                         return TokenName.IDENTIFIER;
 
3737                                 if ((data[++index] == 's') && (data[++index] == 'e'))
 
3738                                         return TokenName.USE;
 
3740                                         return TokenName.IDENTIFIER;
 
3742                                 if ((data[++index] == 'n') && (data[++index] == 's')
 
3743                                                 && (data[++index] == 'e') && (data[++index] == 't'))
 
3744                                         return TokenName.UNSET;
 
3746                         return TokenName.IDENTIFIER;
 
3751                                 if ((data[++index] == 'a') && (data[++index] == 'r'))
 
3752                                         return TokenName.VAR;
 
3754                         return TokenName.IDENTIFIER;
 
3759                                 if ((data[++index] == 'h') && (data[++index] == 'i')
 
3760                                                 && (data[++index] == 'l') && (data[++index] == 'e'))
 
3761                                         return TokenName.WHILE;
 
3762                                 // case 6:if ( (data[++index] =='i') && (data[++index]=='d') &&
 
3763                                 // (data[++index]=='e') && (data[++index]=='f')&&
 
3764                                 // (data[++index]=='p'))
 
3765                                 // return TokenName.widefp ;
 
3767                                 // return TokenName.IDENTIFIER;
 
3769                         return TokenName.IDENTIFIER;
 
3774                                 if ((data[++index] == 'o') && (data[++index] == 'r'))
 
3775                                         return TokenName.OP_XOR_OLD;
 
3777                                         return TokenName.IDENTIFIER;
 
3779                         return TokenName.IDENTIFIER;
 
3781                 return TokenName.IDENTIFIER;
 
3784         public TokenName scanNumber(boolean dotPrefix) throws InvalidInputException {
 
3785                 // when entering this method the currentCharacter is the firt
 
3786                 // digit of the number , i.e. it may be preceeded by a . when
 
3787                 // dotPrefix is true
 
3788                 boolean floating = dotPrefix;
 
3789                 if ((!dotPrefix) && (currentCharacter == '0')) {
 
3790                         if (getNextChar('x', 'X') >= 0) { // ----------hexa-----------------
 
3791                                 // force the first char of the hexa number do exist...
 
3792                                 // consume next character
 
3793                                 unicodeAsBackSlash = false;
 
3794                                 currentCharacter = source[currentPosition++];
 
3795                                 // if (((currentCharacter = source[currentPosition++]) == '\\')
 
3796                                 // && (source[currentPosition] == 'u')) {
 
3797                                 // getNextUnicodeChar();
 
3799                                 // if (withoutUnicodePtr != 0) {
 
3800                                 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
3803                                 if (Character.digit(currentCharacter, 16) == -1)
 
3804                                         throw new InvalidInputException(INVALID_HEXA);
 
3806                                 while (getNextCharAsDigit(16)) {
 
3809                                 // if (getNextChar('l', 'L') >= 0)
 
3810                                 // return TokenName.LongLiteral;
 
3812                                 return TokenName.INTEGERLITERAL;
 
3814                         // there is x or X in the number
 
3815                         // potential octal ! ... some one may write 000099.0 ! thus 00100 <
 
3816                         // 00078.0 is true !!!!! crazy language
 
3817                         if (getNextCharAsDigit()) {
 
3818                                 // -------------potential octal-----------------
 
3819                                 while (getNextCharAsDigit()) {
 
3822                                 // if (getNextChar('l', 'L') >= 0) {
 
3823                                 // return TokenName.LongLiteral;
 
3826                                 // if (getNextChar('f', 'F') >= 0) {
 
3827                                 // return TokenName.FloatingPointLiteral;
 
3829                                 if (getNextChar('d', 'D') >= 0) {
 
3830                                         return TokenName.DOUBLELITERAL;
 
3831                                 } else { // make the distinction between octal and float ....
 
3832                                         if (getNextChar('.')) { // bingo ! ....
 
3833                                                 while (getNextCharAsDigit()) {
 
3836                                                 if (getNextChar('e', 'E') >= 0) {
 
3837                                                         // consume next character
 
3838                                                         unicodeAsBackSlash = false;
 
3839                                                         currentCharacter = source[currentPosition++];
 
3840                                                         // if (((currentCharacter =
 
3841                                                         // source[currentPosition++]) == '\\')
 
3842                                                         // && (source[currentPosition] == 'u')) {
 
3843                                                         // getNextUnicodeChar();
 
3845                                                         // if (withoutUnicodePtr != 0) {
 
3846                                                         // withoutUnicodeBuffer[++withoutUnicodePtr] =
 
3847                                                         // currentCharacter;
 
3850                                                         if ((currentCharacter == '-')
 
3851                                                                         || (currentCharacter == '+')) {
 
3852                                                                 // consume next character
 
3853                                                                 unicodeAsBackSlash = false;
 
3854                                                                 currentCharacter = source[currentPosition++];
 
3855                                                                 // if (((currentCharacter =
 
3856                                                                 // source[currentPosition++]) == '\\')
 
3857                                                                 // && (source[currentPosition] == 'u')) {
 
3858                                                                 // getNextUnicodeChar();
 
3860                                                                 // if (withoutUnicodePtr != 0) {
 
3861                                                                 // withoutUnicodeBuffer[++withoutUnicodePtr] =
 
3862                                                                 // currentCharacter;
 
3866                                                         if (!Character.isDigit(currentCharacter))
 
3867                                                                 throw new InvalidInputException(INVALID_FLOAT);
 
3868                                                         while (getNextCharAsDigit()) {
 
3872                                                 // if (getNextChar('f', 'F') >= 0)
 
3873                                                 // return TokenName.FloatingPointLiteral;
 
3874                                                 getNextChar('d', 'D'); // jump over potential d or D
 
3875                                                 return TokenName.DOUBLELITERAL;
 
3877                                                 return TokenName.INTEGERLITERAL;
 
3884                 while (getNextCharAsDigit()) {
 
3887                 // if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
 
3888                 // return TokenName.LongLiteral;
 
3889                 if ((!dotPrefix) && (getNextChar('.'))) { // decimal part that can be
 
3891                         while (getNextCharAsDigit()) {
 
3896                 // if floating is true both exponant and suffix may be optional
 
3897                 if (getNextChar('e', 'E') >= 0) {
 
3899                         // consume next character
 
3900                         unicodeAsBackSlash = false;
 
3901                         currentCharacter = source[currentPosition++];
 
3902                         // if (((currentCharacter = source[currentPosition++]) == '\\')
 
3903                         // && (source[currentPosition] == 'u')) {
 
3904                         // getNextUnicodeChar();
 
3906                         // if (withoutUnicodePtr != 0) {
 
3907                         // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
3910                         if ((currentCharacter == '-') || (currentCharacter == '+')) { // consume
 
3913                                 unicodeAsBackSlash = false;
 
3914                                 currentCharacter = source[currentPosition++];
 
3915                                 // if (((currentCharacter = source[currentPosition++]) == '\\')
 
3916                                 // && (source[currentPosition] == 'u')) {
 
3917                                 // getNextUnicodeChar();
 
3919                                 // if (withoutUnicodePtr != 0) {
 
3920                                 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
3924                         if (!Character.isDigit(currentCharacter))
 
3925                                 throw new InvalidInputException(INVALID_FLOAT);
 
3926                         while (getNextCharAsDigit()) {
 
3930                 if (getNextChar('d', 'D') >= 0)
 
3931                         return TokenName.DOUBLELITERAL;
 
3932                 // if (getNextChar('f', 'F') >= 0)
 
3933                 // return TokenName.FloatingPointLiteral;
 
3934                 // the long flag has been tested before
 
3935                 return floating ? TokenName.DOUBLELITERAL : TokenName.INTEGERLITERAL;
 
3939          * Search the line number corresponding to a specific position
 
3942         public final int getLineNumber(int position) {
 
3943                 if (lineEnds == null)
 
3945                 int length = linePtr + 1;
 
3948                 int g = 0, d = length - 1;
 
3952                         if (position < lineEnds[m]) {
 
3954                         } else if (position > lineEnds[m]) {
 
3960                 if (position < lineEnds[m]) {
 
3966         public void setPHPMode(boolean mode) {
 
3970         public final void setSource(char[] source) {
 
3971                 setSource(null, source);
 
3974         public final void setSource(ICompilationUnit compilationUnit, char[] source) {
 
3975                 // the source-buffer is set to sourceString
 
3976                 this.compilationUnit = compilationUnit;
 
3977                 if (source == null) {
 
3978                         this.source = new char[0];
 
3980                         this.source = source;
 
3983                 initialPosition = currentPosition = 0;
 
3984                 containsAssertKeyword = false;
 
3985                 withoutUnicodeBuffer = new char[this.source.length];
 
3986                 fFillerToken = TokenName.EOF;
 
3987                 // encapsedStringStack = new Stack();
 
3990         public String toString() {
 
3991                 if (startPosition == source.length)
 
3992                         return "EOF\n\n" + new String(source); //$NON-NLS-1$
 
3993                 if (currentPosition > source.length)
 
3994                         return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
 
3995                 char front[] = new char[startPosition];
 
3996                 System.arraycopy(source, 0, front, 0, startPosition);
 
3997                 int middleLength = (currentPosition - 1) - startPosition + 1;
 
3999                 if (middleLength > -1) {
 
4000                         middle = new char[middleLength];
 
4001                         System.arraycopy(source, startPosition, middle, 0, middleLength);
 
4003                         middle = new char[0];
 
4005                 char end[] = new char[source.length - (currentPosition - 1)];
 
4006                 System.arraycopy(source, (currentPosition - 1) + 1, end, 0,
 
4007                                 source.length - (currentPosition - 1) - 1);
 
4008                 return new String(front)
 
4009                                 + "\n===============================\nStarts here -->" //$NON-NLS-1$
 
4010                                 + new String(middle)
 
4011                                 + "<-- Ends here\n===============================\n" //$NON-NLS-1$
 
4015         public final String toStringAction(TokenName act) {
 
4018                         return "ScannerError"; // + new String(getCurrentTokenSource()) +
 
4022                         return "Inline-HTML(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4023                 case ECHO_INVISIBLE:
 
4027                         return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4029                         return "Variable(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4031                         return "abstract"; //$NON-NLS-1$
 
4033                         return "AND"; //$NON-NLS-1$
 
4035                         return "array"; //$NON-NLS-1$
 
4037                         return "as"; //$NON-NLS-1$
 
4039                         return "break"; //$NON-NLS-1$
 
4041                         return "case"; //$NON-NLS-1$
 
4043                         return "class"; //$NON-NLS-1$
 
4045                         return "catch"; //$NON-NLS-1$
 
4053                         return "continue"; //$NON-NLS-1$
 
4055                         return "default"; //$NON-NLS-1$
 
4057                         // return "define"; //$NON-NLS-1$
 
4059                         return "do"; //$NON-NLS-1$
 
4061                         return "echo"; //$NON-NLS-1$
 
4063                         return "else"; //$NON-NLS-1$
 
4065                         return "elseif"; //$NON-NLS-1$
 
4067                         return "endfor"; //$NON-NLS-1$
 
4069                         return "endforeach"; //$NON-NLS-1$
 
4071                         return "endif"; //$NON-NLS-1$
 
4073                         return "endswitch"; //$NON-NLS-1$
 
4075                         return "endwhile"; //$NON-NLS-1$
 
4079                         return "extends"; //$NON-NLS-1$
 
4081                         // return "false"; //$NON-NLS-1$
 
4083                         return "final"; //$NON-NLS-1$
 
4085                         return "for"; //$NON-NLS-1$
 
4087                         return "foreach"; //$NON-NLS-1$
 
4089                         return "function"; //$NON-NLS-1$
 
4091                         return "global"; //$NON-NLS-1$
 
4093                         return "if"; //$NON-NLS-1$
 
4095                         return "implements"; //$NON-NLS-1$
 
4097                         return "include"; //$NON-NLS-1$
 
4099                         return "include_once"; //$NON-NLS-1$
 
4101                         return "instanceof"; //$NON-NLS-1$
 
4103                         return "interface"; //$NON-NLS-1$
 
4105                         return "isset"; //$NON-NLS-1$
 
4107                         return "list"; //$NON-NLS-1$
 
4109                         return "new"; //$NON-NLS-1$
 
4111                         // return "null"; //$NON-NLS-1$
 
4113                         return "OR"; //$NON-NLS-1$
 
4115                         return "print"; //$NON-NLS-1$
 
4117                         return "private"; //$NON-NLS-1$
 
4119                         return "protected"; //$NON-NLS-1$
 
4121                         return "public"; //$NON-NLS-1$
 
4123                         return "require"; //$NON-NLS-1$
 
4125                         return "require_once"; //$NON-NLS-1$
 
4127                         return "return"; //$NON-NLS-1$
 
4129                         // return "self"; //$NON-NLS-1$
 
4131                         return "static"; //$NON-NLS-1$
 
4133                         return "switch"; //$NON-NLS-1$
 
4135                         // return "true"; //$NON-NLS-1$
 
4137                         return "unset"; //$NON-NLS-1$
 
4139                         return "var"; //$NON-NLS-1$
 
4141                         return "while"; //$NON-NLS-1$
 
4143                         return "XOR"; //$NON-NLS-1$
 
4145                         // return "$this"; //$NON-NLS-1$
 
4146                 case INTEGERLITERAL:
 
4147                         return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4149                         return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4150                 case STRINGDOUBLEQUOTE:
 
4151                         return "StringLiteral(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4152                 case STRINGSINGLEQUOTE:
 
4153                         return "StringConstant(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4154                 case STRINGINTERPOLATED:
 
4155                         return "StringInterpolated(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4156                 case ENCAPSEDSTRING0:
 
4157                         return "`"; //$NON-NLS-1$
 
4158                         // case EncapsedString1:
 
4159                         // return "\'"; //$NON-NLS-1$
 
4160                         // case EncapsedString2:
 
4161                         // return "\""; //$NON-NLS-1$
 
4163                         return "STRING_DQ(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
4165                         return "HEREDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
 
4167                         return "++"; //$NON-NLS-1$
 
4169                         return "--"; //$NON-NLS-1$
 
4171                         return "=="; //$NON-NLS-1$
 
4172                 case EQUAL_EQUAL_EQUAL:
 
4173                         return "==="; //$NON-NLS-1$
 
4175                         return "=>"; //$NON-NLS-1$
 
4177                         return "<="; //$NON-NLS-1$
 
4179                         return ">="; //$NON-NLS-1$
 
4181                         return "!="; //$NON-NLS-1$
 
4182                 case NOT_EQUAL_EQUAL:
 
4183                         return "!=="; //$NON-NLS-1$
 
4185                         return "<<"; //$NON-NLS-1$
 
4187                         return ">>"; //$NON-NLS-1$
 
4189                         return "+="; //$NON-NLS-1$
 
4191                         return "-="; //$NON-NLS-1$
 
4192                 case MULTIPLY_EQUAL:
 
4193                         return "*="; //$NON-NLS-1$
 
4195                         return "/="; //$NON-NLS-1$
 
4197                         return "&="; //$NON-NLS-1$
 
4199                         return "|="; //$NON-NLS-1$
 
4201                         return "^="; //$NON-NLS-1$
 
4202                 case REMAINDER_EQUAL:
 
4203                         return "%="; //$NON-NLS-1$
 
4205                         return ".="; //$NON-NLS-1$
 
4206                 case LEFT_SHIFT_EQUAL:
 
4207                         return "<<="; //$NON-NLS-1$
 
4208                 case RIGHT_SHIFT_EQUAL:
 
4209                         return ">>="; //$NON-NLS-1$
 
4211                         return "||"; //$NON-NLS-1$
 
4213                         return "&&"; //$NON-NLS-1$
 
4215                         return "+"; //$NON-NLS-1$
 
4217                         return "-"; //$NON-NLS-1$
 
4221                         return "!"; //$NON-NLS-1$
 
4223                         return "%"; //$NON-NLS-1$
 
4225                         return "^"; //$NON-NLS-1$
 
4227                         return "&"; //$NON-NLS-1$
 
4229                         return "*"; //$NON-NLS-1$
 
4231                         return "|"; //$NON-NLS-1$
 
4233                         return "~"; //$NON-NLS-1$
 
4235                         return "~="; //$NON-NLS-1$
 
4237                         return "/"; //$NON-NLS-1$
 
4239                         return ">"; //$NON-NLS-1$
 
4241                         return "<"; //$NON-NLS-1$
 
4243                         return "("; //$NON-NLS-1$
 
4245                         return ")"; //$NON-NLS-1$
 
4247                         return "{"; //$NON-NLS-1$
 
4249                         return "}"; //$NON-NLS-1$
 
4251                         return "["; //$NON-NLS-1$
 
4253                         return "]"; //$NON-NLS-1$
 
4255                         return ";"; //$NON-NLS-1$
 
4257                         return "?"; //$NON-NLS-1$
 
4259                         return ":"; //$NON-NLS-1$
 
4261                         return ","; //$NON-NLS-1$
 
4263                         return "."; //$NON-NLS-1$
 
4265                         return "="; //$NON-NLS-1$
 
4275                         return "EOF"; //$NON-NLS-1$
 
4277                         return "WHITESPACE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
 
4279                         return "COMMENT_LINE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
 
4281                         return "COMMENT_BLOCK(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
 
4282                 case COMMENT_PHPDOC:
 
4283                         return "COMMENT_PHPDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
 
4285                         // return "HTML(" + new String(getCurrentTokenSource()) + ")";
 
4288                         return "__FILE__"; //$NON-NLS-1$
 
4290                         return "__LINE__"; //$NON-NLS-1$
 
4292                         return "__CLASS__"; //$NON-NLS-1$
 
4294                         return "__METHOD__"; //$NON-NLS-1$
 
4296                         return "__FUNCTION__"; //$NON-NLS-1
 
4298                         return "( bool )"; //$NON-NLS-1$
 
4300                         return "( int )"; //$NON-NLS-1$
 
4302                         return "( double )"; //$NON-NLS-1$
 
4304                         return "( object )"; //$NON-NLS-1$
 
4306                         return "( string )"; //$NON-NLS-1$
 
4308             return "( namespace )"; //$NON-NLS-1$
 
4310                         return "token not handled (" + (act.toString ()) + ") " + new String(getCurrentTokenSource()); //$NON-NLS-1$
 
4318         public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace) {
 
4319                 this(tokenizeComments, tokenizeWhiteSpace, false);
 
4322         public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
 
4323                         boolean checkNonExternalizedStringLiterals) {
 
4324                 this(tokenizeComments, tokenizeWhiteSpace,
 
4325                                 checkNonExternalizedStringLiterals, false);
 
4328         public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
 
4329                         boolean checkNonExternalizedStringLiterals, boolean assertMode) {
 
4330                 this(tokenizeComments, tokenizeWhiteSpace,
 
4331                                 checkNonExternalizedStringLiterals, assertMode, false, null,
 
4335         public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
 
4336                         boolean checkNonExternalizedStringLiterals, boolean assertMode,
 
4337                         boolean tokenizeStrings, char[][] taskTags,
 
4338                         char[][] taskPriorities, boolean isTaskCaseSensitive) {
 
4339                 this.eofPosition = Integer.MAX_VALUE;
 
4340                 this.tokenizeComments = tokenizeComments;
 
4341                 this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 
4342                 this.tokenizeStrings = tokenizeStrings;
 
4343                 this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
 
4344                 // this.assertMode = assertMode;
 
4345                 // this.encapsedStringStack = null;
 
4346                 this.taskTags = taskTags;
 
4347                 this.taskPriorities = taskPriorities;
 
4350         private void checkNonExternalizeString() throws InvalidInputException {
 
4351                 if (currentLine == null)
 
4353                 parseTags(currentLine);
 
4356         private void parseTags(NLSLine line) throws InvalidInputException {
 
4357                 String s = new String(getCurrentTokenSource());
 
4358                 int pos = s.indexOf(TAG_PREFIX);
 
4359                 int lineLength = line.size();
 
4361                         int start = pos + TAG_PREFIX_LENGTH;
 
4362                         int end = s.indexOf(TAG_POSTFIX, start);
 
4363                         String index = s.substring(start, end);
 
4366                                 i = Integer.parseInt(index) - 1;
 
4367                                 // Tags are one based not zero based.
 
4368                         } catch (NumberFormatException e) {
 
4369                                 i = -1; // we don't want to consider this as a valid NLS tag
 
4371                         if (line.exists(i)) {
 
4374                         pos = s.indexOf(TAG_PREFIX, start);
 
4376                 this.nonNLSStrings = new StringLiteral[lineLength];
 
4377                 int nonNLSCounter = 0;
 
4378                 for (Iterator iterator = line.iterator(); iterator.hasNext();) {
 
4379                         StringLiteral literal = (StringLiteral) iterator.next();
 
4380                         if (literal != null) {
 
4381                                 this.nonNLSStrings[nonNLSCounter++] = literal;
 
4384                 if (nonNLSCounter == 0) {
 
4385                         this.nonNLSStrings = null;
 
4389                 this.wasNonExternalizedStringLiteral = true;
 
4390                 if (nonNLSCounter != lineLength) {
 
4391                         System.arraycopy(this.nonNLSStrings, 0,
 
4392                                         (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0,
 
4398         public final void scanEscapeCharacter() throws InvalidInputException {
 
4399                 // the string with "\\u" is a legal string of two chars \ and u
 
4400                 // thus we use a direct access to the source (for regular cases).
 
4401                 if (unicodeAsBackSlash) {
 
4402                         // consume next character
 
4403                         unicodeAsBackSlash = false;
 
4404                         // if (((currentCharacter = source[currentPosition++]) == '\\') &&
 
4405                         // (source[currentPosition] == 'u')) {
 
4406                         // getNextUnicodeChar();
 
4408                         if (withoutUnicodePtr != 0) {
 
4409                                 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 
4413                         currentCharacter = source[currentPosition++];
 
4414                 switch (currentCharacter) {
 
4416                         currentCharacter = '\b';
 
4419                         currentCharacter = '\t';
 
4422                         currentCharacter = '\n';
 
4425                         currentCharacter = '\f';
 
4428                         currentCharacter = '\r';
 
4431                         currentCharacter = '\"';
 
4434                         currentCharacter = '\'';
 
4437                         currentCharacter = '\\';
 
4440                         // -----------octal escape--------------
 
4442                         // OctalDigit OctalDigit
 
4443                         // ZeroToThree OctalDigit OctalDigit
 
4444                         int number = Character.getNumericValue(currentCharacter);
 
4445                         if (number >= 0 && number <= 7) {
 
4446                                 boolean zeroToThreeNot = number > 3;
 
4448                                                 .isDigit(currentCharacter = source[currentPosition++])) {
 
4449                                         int digit = Character.getNumericValue(currentCharacter);
 
4450                                         if (digit >= 0 && digit <= 7) {
 
4451                                                 number = (number * 8) + digit;
 
4453                                                                 .isDigit(currentCharacter = source[currentPosition++])) {
 
4454                                                         if (zeroToThreeNot) { // has read \NotZeroToThree
 
4456                                                                 // Digit --> ignore last character
 
4460                                                                                 .getNumericValue(currentCharacter);
 
4461                                                                 if (digit >= 0 && digit <= 7) { // has read
 
4463                                                                         // OctalDigit OctalDigit
 
4464                                                                         number = (number * 8) + digit;
 
4465                                                                 } else { // has read \ZeroToThree OctalDigit
 
4467                                                                         // --> ignore last character
 
4471                                                 } else { // has read \OctalDigit NonDigit--> ignore
 
4476                                         } else { // has read \OctalDigit NonOctalDigit--> ignore
 
4481                                 } else { // has read \OctalDigit --> ignore last character
 
4485                                         throw new InvalidInputException(INVALID_ESCAPE);
 
4486                                 currentCharacter = (char) number;
 
4488                                 throw new InvalidInputException(INVALID_ESCAPE);
 
4492         // chech presence of task: tags
 
4493         // TODO (frederic) see if we need to take unicode characters into account...
 
4494         public void checkTaskTag(int commentStart, int commentEnd) {
 
4495                 char[] src = this.source;
 
4497                 // only look for newer task: tags
 
4498                 if (this.foundTaskCount > 0
 
4499                                 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
 
4502                 int foundTaskIndex = this.foundTaskCount;
 
4503                 char previous = src[commentStart + 1]; // should be '*' or '/'
 
4504                 nextChar: for (int i = commentStart + 2; i < commentEnd
 
4505                                 && i < this.eofPosition; i++) {
 
4507                         char[] priority = null;
 
4508                         // check for tag occurrence only if not ambiguous with javadoc tag
 
4509                         if (previous != '@') {
 
4510                                 nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) {
 
4511                                         tag = this.taskTags[itag];
 
4512                                         int tagLength = tag.length;
 
4516                                         // ensure tag is not leaded with letter if tag starts with a
 
4518                                         if (Scanner.isPHPIdentifierStart(tag[0])) {
 
4519                                                 if (Scanner.isPHPIdentifierPart(previous)) {
 
4524                                         for (int t = 0; t < tagLength; t++) {
 
4527                                                 if (x >= this.eofPosition || x >= commentEnd)
 
4529                                                 if ((sc = src[i + t]) != (tc = tag[t])) { // case
 
4532                                                         if (this.isTaskCaseSensitive
 
4533                                                                         || (Character.toLowerCase(sc) != Character
 
4534                                                                                         .toLowerCase(tc))) { // case
 
4541                                         // ensure tag is not followed with letter if tag finishes
 
4544                                         if (i + tagLength < commentEnd
 
4545                                                         && Scanner.isPHPIdentifierPart(src[i + tagLength
 
4547                                                 if (Scanner.isPHPIdentifierPart(src[i + tagLength]))
 
4550                                         if (this.foundTaskTags == null) {
 
4551                                                 this.foundTaskTags = new char[5][];
 
4552                                                 this.foundTaskMessages = new char[5][];
 
4553                                                 this.foundTaskPriorities = new char[5][];
 
4554                                                 this.foundTaskPositions = new int[5][];
 
4555                                         } else if (this.foundTaskCount == this.foundTaskTags.length) {
 
4560                                                                                 this.foundTaskTags = new char[this.foundTaskCount * 2][],
 
4561                                                                                 0, this.foundTaskCount);
 
4564                                                                                 this.foundTaskMessages,
 
4566                                                                                 this.foundTaskMessages = new char[this.foundTaskCount * 2][],
 
4567                                                                                 0, this.foundTaskCount);
 
4570                                                                                 this.foundTaskPriorities,
 
4572                                                                                 this.foundTaskPriorities = new char[this.foundTaskCount * 2][],
 
4573                                                                                 0, this.foundTaskCount);
 
4576                                                                                 this.foundTaskPositions,
 
4578                                                                                 this.foundTaskPositions = new int[this.foundTaskCount * 2][],
 
4579                                                                                 0, this.foundTaskCount);
 
4582                                         priority = this.taskPriorities != null
 
4583                                                         && itag < this.taskPriorities.length ? this.taskPriorities[itag]
 
4586                                         this.foundTaskTags[this.foundTaskCount] = tag;
 
4587                                         this.foundTaskPriorities[this.foundTaskCount] = priority;
 
4588                                         this.foundTaskPositions[this.foundTaskCount] = new int[] {
 
4589                                                         i, i + tagLength - 1 };
 
4590                                         this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
 
4591                                         this.foundTaskCount++;
 
4592                                         i += tagLength - 1; // will be incremented when looping
 
4598                 for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 
4599                         // retrieve message start and end positions
 
4600                         int msgStart = this.foundTaskPositions[i][0]
 
4601                                         + this.foundTaskTags[i].length;
 
4602                         int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1
 
4604                         // at most beginning of next task
 
4605                         if (max_value < msgStart) {
 
4606                                 max_value = msgStart; // would only occur if tag is before
 
4611                         for (int j = msgStart; j < max_value; j++) {
 
4612                                 if ((c = src[j]) == '\n' || c == '\r') {
 
4618                                 for (int j = max_value; j > msgStart; j--) {
 
4619                                         if ((c = src[j]) == '*') {
 
4627                         if (msgStart == end)
 
4630                         while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
 
4632                         while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end)
 
4634                         // update the end position of the task
 
4635                         this.foundTaskPositions[i][1] = end;
 
4636                         // get the message source
 
4637                         final int messageLength = end - msgStart + 1;
 
4638                         char[] message = new char[messageLength];
 
4639                         System.arraycopy(src, msgStart, message, 0, messageLength);
 
4640                         this.foundTaskMessages[i] = message;
 
4644         // chech presence of task: tags
 
4645         // public void checkTaskTag(int commentStart, int commentEnd) {
 
4646         // // only look for newer task: tags
 
4647         // if (this.foundTaskCount > 0 &&
 
4648         // this.foundTaskPositions[this.foundTaskCount
 
4649         // - 1][0] >= commentStart) {
 
4652         // int foundTaskIndex = this.foundTaskCount;
 
4653         // nextChar: for (int i = commentStart; i < commentEnd && i <
 
4654         // this.eofPosition; i++) {
 
4655         // char[] tag = null;
 
4656         // char[] priority = null;
 
4657         // // check for tag occurrence
 
4658         // nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) {
 
4659         // tag = this.taskTags[itag];
 
4660         // priority = this.taskPriorities != null && itag <
 
4661         // this.taskPriorities.length
 
4662         // ? this.taskPriorities[itag] : null;
 
4663         // int tagLength = tag.length;
 
4664         // for (int t = 0; t < tagLength; t++) {
 
4665         // if (this.source[i + t] != tag[t])
 
4666         // continue nextTag;
 
4668         // if (this.foundTaskTags == null) {
 
4669         // this.foundTaskTags = new char[5][];
 
4670         // this.foundTaskMessages = new char[5][];
 
4671         // this.foundTaskPriorities = new char[5][];
 
4672         // this.foundTaskPositions = new int[5][];
 
4673         // } else if (this.foundTaskCount == this.foundTaskTags.length) {
 
4674         // System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new
 
4675         // char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
 
4676         // System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new
 
4677         // char[this.foundTaskCount * 2][], 0,
 
4678         // this.foundTaskCount);
 
4679         // System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities =
 
4680         // new char[this.foundTaskCount * 2][], 0,
 
4681         // this.foundTaskCount);
 
4682         // System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions =
 
4684         // int[this.foundTaskCount * 2][], 0,
 
4685         // this.foundTaskCount);
 
4687         // this.foundTaskTags[this.foundTaskCount] = tag;
 
4688         // this.foundTaskPriorities[this.foundTaskCount] = priority;
 
4689         // this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i +
 
4692         // this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
 
4693         // this.foundTaskCount++;
 
4694         // i += tagLength - 1; // will be incremented when looping
 
4697         // for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 
4698         // // retrieve message start and end positions
 
4699         // int msgStart = this.foundTaskPositions[i][0] +
 
4700         // this.foundTaskTags[i].length;
 
4701         // int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i +
 
4702         // 1][0] - 1 : commentEnd - 1;
 
4703         // // at most beginning of next task
 
4704         // if (max_value < msgStart)
 
4705         // max_value = msgStart; // would only occur if tag is before EOF.
 
4708         // for (int j = msgStart; j < max_value; j++) {
 
4709         // if ((c = this.source[j]) == '\n' || c == '\r') {
 
4715         // for (int j = max_value; j > msgStart; j--) {
 
4716         // if ((c = this.source[j]) == '*') {
 
4724         // if (msgStart == end)
 
4725         // continue; // empty
 
4726         // // trim the message
 
4727         // while (CharOperation.isWhitespace(source[end]) && msgStart <= end)
 
4729         // while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end)
 
4731         // // update the end position of the task
 
4732         // this.foundTaskPositions[i][1] = end;
 
4733         // // get the message source
 
4734         // final int messageLength = end - msgStart + 1;
 
4735         // char[] message = new char[messageLength];
 
4736         // System.arraycopy(source, msgStart, message, 0, messageLength);
 
4737         // this.foundTaskMessages[i] = message;