1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
12 import java.util.ArrayList;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Stack;
16 import net.sourceforge.phpdt.core.compiler.CharOperation;
17 import net.sourceforge.phpdt.core.compiler.IScanner;
18 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
19 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
20 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
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 the
27 * stream - currentPosition-1 gives the sourceEnd position into the stream
30 private boolean assertMode;
31 public boolean useAssertAsAnIndentifier = false;
32 //flag indicating if processed source contains occurrences of keyword assert
33 public boolean containsAssertKeyword = false;
34 public boolean recordLineSeparator;
35 public boolean phpMode = false;
36 public Stack encapsedStringStack = null;
37 public char currentCharacter;
38 public int startPosition;
39 public int currentPosition;
40 public int initialPosition, eofPosition;
41 // after this position eof are generated instead of real token from the
43 public boolean tokenizeComments;
44 public boolean tokenizeWhiteSpace;
45 public boolean tokenizeStrings;
46 //source should be viewed as a window (aka a part)
47 //of a entire very large stream
50 public char[] withoutUnicodeBuffer;
51 public int withoutUnicodePtr;
52 //when == 0 ==> no unicode in the current token
53 public boolean unicodeAsBackSlash = false;
54 public boolean scanningFloatLiteral = false;
55 //support for /** comments
56 //public char[][] comments = new char[10][];
57 public int[] commentStops = new int[10];
58 public int[] commentStarts = new int[10];
59 public int commentPtr = -1; // no comment test with commentPtr value -1
60 //diet parsing support - jump over some method body when requested
61 public boolean diet = false;
62 //support for the poor-line-debuggers ....
63 //remember the position of the cr/lf
64 public int[] lineEnds = new int[250];
65 public int linePtr = -1;
66 public boolean wasAcr = false;
67 public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
68 public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
69 public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
70 public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$
71 public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
72 public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
73 public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
74 public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
75 public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
76 public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
77 public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
78 public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
79 //----------------optimized identifier managment------------------
80 static final char[] charArray_a = new char[]{'a'},
81 charArray_b = new char[]{'b'}, charArray_c = new char[]{'c'},
82 charArray_d = new char[]{'d'}, charArray_e = new char[]{'e'},
83 charArray_f = new char[]{'f'}, charArray_g = new char[]{'g'},
84 charArray_h = new char[]{'h'}, charArray_i = new char[]{'i'},
85 charArray_j = new char[]{'j'}, charArray_k = new char[]{'k'},
86 charArray_l = new char[]{'l'}, charArray_m = new char[]{'m'},
87 charArray_n = new char[]{'n'}, charArray_o = new char[]{'o'},
88 charArray_p = new char[]{'p'}, charArray_q = new char[]{'q'},
89 charArray_r = new char[]{'r'}, charArray_s = new char[]{'s'},
90 charArray_t = new char[]{'t'}, charArray_u = new char[]{'u'},
91 charArray_v = new char[]{'v'}, charArray_w = new char[]{'w'},
92 charArray_x = new char[]{'x'}, charArray_y = new char[]{'y'},
93 charArray_z = new char[]{'z'};
94 static final char[] initCharArray = new char[]{'\u0000', '\u0000', '\u0000',
95 '\u0000', '\u0000', '\u0000'};
96 static final int TableSize = 30, InternalTableSize = 6;
98 public static final int OptimizedLength = 6;
100 final char[][][][] charArray_length = new char[OptimizedLength][TableSize][InternalTableSize][];
101 // support for detecting non-externalized string literals
102 int currentLineNr = -1;
103 int previousLineNr = -1;
104 NLSLine currentLine = null;
105 List lines = new ArrayList();
106 public static final String TAG_PREFIX = "//$NON-NLS-"; //$NON-NLS-1$
107 public static final int TAG_PREFIX_LENGTH = TAG_PREFIX.length();
108 public static final String TAG_POSTFIX = "$"; //$NON-NLS-1$
109 public static final int TAG_POSTFIX_LENGTH = TAG_POSTFIX.length();
110 public StringLiteral[] nonNLSStrings = null;
111 public boolean checkNonExternalizedStringLiterals = true;
112 public boolean wasNonExternalizedStringLiteral = false;
114 for (int i = 0; i < 6; i++) {
115 for (int j = 0; j < TableSize; j++) {
116 for (int k = 0; k < InternalTableSize; k++) {
117 charArray_length[i][j][k] = initCharArray;
122 static int newEntry2 = 0, newEntry3 = 0, newEntry4 = 0, newEntry5 = 0,
124 public static final int RoundBracket = 0;
125 public static final int SquareBracket = 1;
126 public static final int CurlyBracket = 2;
127 public static final int BracketKinds = 3;
129 public char[][] foundTaskTags = null;
130 public char[][] foundTaskMessages;
131 public char[][] foundTaskPriorities = null;
132 public int[][] foundTaskPositions;
133 public int foundTaskCount = 0;
134 public char[][] taskTags = null;
135 public char[][] taskPriorities = null;
136 public static final boolean DEBUG = false;
137 public static final boolean TRACE = false;
141 public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace) {
142 this(tokenizeComments, tokenizeWhiteSpace, false);
145 * Determines if the specified character is permissible as the first
146 * character in a PHP identifier
148 public static boolean isPHPIdentifierStart(char ch) {
149 return Character.isLetter(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
152 * Determines if the specified character may be part of a PHP identifier as
153 * other than the first character
155 public static boolean isPHPIdentifierPart(char ch) {
156 return Character.isLetterOrDigit(ch) || (ch == '_')
157 || (0x7F <= ch && ch <= 0xFF);
159 public final boolean atEnd() {
160 // This code is not relevant if source is
161 // Only a part of the real stream input
162 return source.length == currentPosition;
164 public char[] getCurrentIdentifierSource() {
165 //return the token REAL source (aka unicodes are precomputed)
167 // if (withoutUnicodePtr != 0)
168 // //0 is used as a fast test flag so the real first char is in position 1
170 // withoutUnicodeBuffer,
172 // result = new char[withoutUnicodePtr],
174 // withoutUnicodePtr);
176 int length = currentPosition - startPosition;
177 switch (length) { // see OptimizedLength
179 return optimizedCurrentTokenSource1();
181 return optimizedCurrentTokenSource2();
183 return optimizedCurrentTokenSource3();
185 return optimizedCurrentTokenSource4();
187 return optimizedCurrentTokenSource5();
189 return optimizedCurrentTokenSource6();
192 System.arraycopy(source, startPosition, result = new char[length], 0,
197 public int getCurrentTokenEndPosition() {
198 return this.currentPosition - 1;
200 public final char[] getCurrentTokenSource() {
201 // Return the token REAL source (aka unicodes are precomputed)
203 // if (withoutUnicodePtr != 0)
204 // // 0 is used as a fast test flag so the real first char is in position 1
206 // withoutUnicodeBuffer,
208 // result = new char[withoutUnicodePtr],
210 // withoutUnicodePtr);
213 System.arraycopy(source, startPosition,
214 result = new char[length = currentPosition - startPosition], 0, length);
218 public final char[] getCurrentTokenSource(int startPos) {
219 // Return the token REAL source (aka unicodes are precomputed)
221 // if (withoutUnicodePtr != 0)
222 // // 0 is used as a fast test flag so the real first char is in position 1
224 // withoutUnicodeBuffer,
226 // result = new char[withoutUnicodePtr],
228 // withoutUnicodePtr);
231 System.arraycopy(source, startPos,
232 result = new char[length = currentPosition - startPos], 0, length);
236 public final char[] getCurrentTokenSourceString() {
237 //return the token REAL source (aka unicodes are precomputed).
238 //REMOVE the two " that are at the beginning and the end.
240 if (withoutUnicodePtr != 0)
241 //0 is used as a fast test flag so the real first char is in position 1
242 System.arraycopy(withoutUnicodeBuffer, 2,
243 //2 is 1 (real start) + 1 (to jump over the ")
244 result = new char[withoutUnicodePtr - 2], 0, withoutUnicodePtr - 2);
247 System.arraycopy(source, startPosition + 1,
248 result = new char[length = currentPosition - startPosition - 2], 0,
253 public int getCurrentTokenStartPosition() {
254 return this.startPosition;
256 public final char[] getCurrentStringLiteralSource() {
257 // Return the token REAL source (aka unicodes are precomputed)
260 System.arraycopy(source, startPosition + 1,
261 result = new char[length = currentPosition - startPosition - 2], 0,
267 * Search the source position corresponding to the end of a given line number
269 * Line numbers are 1-based, and relative to the scanner initialPosition.
270 * Character positions are 0-based.
272 * In case the given line number is inconsistent, answers -1.
274 public final int getLineEnd(int lineNumber) {
275 if (lineEnds == null)
277 if (lineNumber >= lineEnds.length)
281 if (lineNumber == lineEnds.length - 1)
283 return lineEnds[lineNumber - 1];
284 // next line start one character behind the lineEnd of the previous line
287 * Search the source position corresponding to the beginning of a given line
290 * Line numbers are 1-based, and relative to the scanner initialPosition.
291 * Character positions are 0-based.
293 * e.g. getLineStart(1) --> 0 i.e. first line starts at character 0.
295 * In case the given line number is inconsistent, answers -1.
297 public final int getLineStart(int lineNumber) {
298 if (lineEnds == null)
300 if (lineNumber >= lineEnds.length)
305 return initialPosition;
306 return lineEnds[lineNumber - 2] + 1;
307 // next line start one character behind the lineEnd of the previous line
309 public final boolean getNextChar(char testedChar) {
311 //handle the case of unicode.
312 //when a unicode appears then we must use a buffer that holds char
314 //At the end of this method currentCharacter holds the new visited char
315 //and currentPosition points right next after it
316 //Both previous lines are true if the currentCharacter is == to the
318 //On false, no side effect has occured.
319 //ALL getNextChar.... ARE OPTIMIZED COPIES
320 int temp = currentPosition;
322 currentCharacter = source[currentPosition++];
323 // if (((currentCharacter = source[currentPosition++]) == '\\')
324 // && (source[currentPosition] == 'u')) {
325 // //-------------unicode traitement ------------
326 // int c1, c2, c3, c4;
327 // int unicodeSize = 6;
328 // currentPosition++;
329 // while (source[currentPosition] == 'u') {
330 // currentPosition++;
334 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
336 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
338 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
340 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
342 // currentPosition = temp;
346 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
347 // if (currentCharacter != testedChar) {
348 // currentPosition = temp;
351 // unicodeAsBackSlash = currentCharacter == '\\';
353 // //need the unicode buffer
354 // if (withoutUnicodePtr == 0) {
355 // //buffer all the entries that have been left aside....
356 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
360 // withoutUnicodeBuffer,
362 // withoutUnicodePtr);
364 // //fill the buffer with the char
365 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
368 // } //-------------end unicode traitement--------------
370 if (currentCharacter != testedChar) {
371 currentPosition = temp;
374 unicodeAsBackSlash = false;
375 // if (withoutUnicodePtr != 0)
376 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
379 } catch (IndexOutOfBoundsException e) {
380 unicodeAsBackSlash = false;
381 currentPosition = temp;
385 public final int getNextChar(char testedChar1, char testedChar2) {
386 //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
387 //test can be done with (x==0) for the first and (x>0) for the second
388 //handle the case of unicode.
389 //when a unicode appears then we must use a buffer that holds char
391 //At the end of this method currentCharacter holds the new visited char
392 //and currentPosition points right next after it
393 //Both previous lines are true if the currentCharacter is == to the
395 //On false, no side effect has occured.
396 //ALL getNextChar.... ARE OPTIMIZED COPIES
397 int temp = currentPosition;
400 currentCharacter = source[currentPosition++];
401 // if (((currentCharacter = source[currentPosition++]) == '\\')
402 // && (source[currentPosition] == 'u')) {
403 // //-------------unicode traitement ------------
404 // int c1, c2, c3, c4;
405 // int unicodeSize = 6;
406 // currentPosition++;
407 // while (source[currentPosition] == 'u') {
408 // currentPosition++;
412 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
414 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
416 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
418 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
420 // currentPosition = temp;
424 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
425 // if (currentCharacter == testedChar1)
427 // else if (currentCharacter == testedChar2)
430 // currentPosition = temp;
434 // //need the unicode buffer
435 // if (withoutUnicodePtr == 0) {
436 // //buffer all the entries that have been left aside....
437 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
441 // withoutUnicodeBuffer,
443 // withoutUnicodePtr);
445 // //fill the buffer with the char
446 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
448 // } //-------------end unicode traitement--------------
450 if (currentCharacter == testedChar1)
452 else if (currentCharacter == testedChar2)
455 currentPosition = temp;
458 // if (withoutUnicodePtr != 0)
459 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
462 } catch (IndexOutOfBoundsException e) {
463 currentPosition = temp;
467 public final boolean getNextCharAsDigit() {
469 //handle the case of unicode.
470 //when a unicode appears then we must use a buffer that holds char
472 //At the end of this method currentCharacter holds the new visited char
473 //and currentPosition points right next after it
474 //Both previous lines are true if the currentCharacter is a digit
475 //On false, no side effect has occured.
476 //ALL getNextChar.... ARE OPTIMIZED COPIES
477 int temp = currentPosition;
479 currentCharacter = source[currentPosition++];
480 // if (((currentCharacter = source[currentPosition++]) == '\\')
481 // && (source[currentPosition] == 'u')) {
482 // //-------------unicode traitement ------------
483 // int c1, c2, c3, c4;
484 // int unicodeSize = 6;
485 // currentPosition++;
486 // while (source[currentPosition] == 'u') {
487 // currentPosition++;
491 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
493 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
495 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
497 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
499 // currentPosition = temp;
503 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
504 // if (!Character.isDigit(currentCharacter)) {
505 // currentPosition = temp;
509 // //need the unicode buffer
510 // if (withoutUnicodePtr == 0) {
511 // //buffer all the entries that have been left aside....
512 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
516 // withoutUnicodeBuffer,
518 // withoutUnicodePtr);
520 // //fill the buffer with the char
521 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
523 // } //-------------end unicode traitement--------------
525 if (!Character.isDigit(currentCharacter)) {
526 currentPosition = temp;
529 // if (withoutUnicodePtr != 0)
530 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
533 } catch (IndexOutOfBoundsException e) {
534 currentPosition = temp;
538 public final boolean getNextCharAsDigit(int radix) {
540 //handle the case of unicode.
541 //when a unicode appears then we must use a buffer that holds char
543 //At the end of this method currentCharacter holds the new visited char
544 //and currentPosition points right next after it
545 //Both previous lines are true if the currentCharacter is a digit base on
547 //On false, no side effect has occured.
548 //ALL getNextChar.... ARE OPTIMIZED COPIES
549 int temp = currentPosition;
551 currentCharacter = source[currentPosition++];
552 // if (((currentCharacter = source[currentPosition++]) == '\\')
553 // && (source[currentPosition] == 'u')) {
554 // //-------------unicode traitement ------------
555 // int c1, c2, c3, c4;
556 // int unicodeSize = 6;
557 // currentPosition++;
558 // while (source[currentPosition] == 'u') {
559 // currentPosition++;
563 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
565 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
567 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
569 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
571 // currentPosition = temp;
575 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
576 // if (Character.digit(currentCharacter, radix) == -1) {
577 // currentPosition = temp;
581 // //need the unicode buffer
582 // if (withoutUnicodePtr == 0) {
583 // //buffer all the entries that have been left aside....
584 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
588 // withoutUnicodeBuffer,
590 // withoutUnicodePtr);
592 // //fill the buffer with the char
593 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
595 // } //-------------end unicode traitement--------------
597 if (Character.digit(currentCharacter, radix) == -1) {
598 currentPosition = temp;
601 // if (withoutUnicodePtr != 0)
602 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
605 } catch (IndexOutOfBoundsException e) {
606 currentPosition = temp;
610 public boolean getNextCharAsJavaIdentifierPart() {
612 //handle the case of unicode.
613 //when a unicode appears then we must use a buffer that holds char
615 //At the end of this method currentCharacter holds the new visited char
616 //and currentPosition points right next after it
617 //Both previous lines are true if the currentCharacter is a
618 // JavaIdentifierPart
619 //On false, no side effect has occured.
620 //ALL getNextChar.... ARE OPTIMIZED COPIES
621 int temp = currentPosition;
623 currentCharacter = source[currentPosition++];
624 // if (((currentCharacter = source[currentPosition++]) == '\\')
625 // && (source[currentPosition] == 'u')) {
626 // //-------------unicode traitement ------------
627 // int c1, c2, c3, c4;
628 // int unicodeSize = 6;
629 // currentPosition++;
630 // while (source[currentPosition] == 'u') {
631 // currentPosition++;
635 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
637 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
639 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
641 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
643 // currentPosition = temp;
647 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
648 // if (!isPHPIdentifierPart(currentCharacter)) {
649 // currentPosition = temp;
653 // //need the unicode buffer
654 // if (withoutUnicodePtr == 0) {
655 // //buffer all the entries that have been left aside....
656 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
660 // withoutUnicodeBuffer,
662 // withoutUnicodePtr);
664 // //fill the buffer with the char
665 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
667 // } //-------------end unicode traitement--------------
669 if (!isPHPIdentifierPart(currentCharacter)) {
670 currentPosition = temp;
673 // if (withoutUnicodePtr != 0)
674 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
677 } catch (IndexOutOfBoundsException e) {
678 currentPosition = temp;
682 public int getCastOrParen() {
683 int tempPosition = currentPosition;
684 char tempCharacter = currentCharacter;
685 int tempToken = TokenNameLPAREN;
686 boolean found = false;
687 StringBuffer buf = new StringBuffer();
690 currentCharacter = source[currentPosition++];
691 } while (currentCharacter == ' ' || currentCharacter == '\t');
692 while ((currentCharacter >= 'a' && currentCharacter <= 'z')
693 || (currentCharacter >= 'A' && currentCharacter <= 'Z')) {
694 buf.append(currentCharacter);
695 currentCharacter = source[currentPosition++];
697 if (buf.length() >= 3 && buf.length() <= 7) {
698 char[] data = buf.toString().toCharArray();
700 switch (data.length) {
703 if ((data[index] == 'i') && (data[++index] == 'n')
704 && (data[++index] == 't')) {
706 tempToken = TokenNameintCAST;
711 if ((data[index] == 'b') && (data[++index] == 'o')
712 && (data[++index] == 'o') && (data[++index] == 'l')) {
714 tempToken = TokenNameboolCAST;
717 if ((data[index] == 'r') && (data[++index] == 'e')
718 && (data[++index] == 'a') && (data[++index] == 'l')) {
720 tempToken = TokenNamedoubleCAST;
726 if ((data[index] == 'a') && (data[++index] == 'r')
727 && (data[++index] == 'r') && (data[++index] == 'a')
728 && (data[++index] == 'y')) {
730 tempToken = TokenNamearrayCAST;
733 if ((data[index] == 'u') && (data[++index] == 'n')
734 && (data[++index] == 's') && (data[++index] == 'e')
735 && (data[++index] == 't')) {
737 tempToken = TokenNameunsetCAST;
740 if ((data[index] == 'f') && (data[++index] == 'l')
741 && (data[++index] == 'o') && (data[++index] == 'a')
742 && (data[++index] == 't')) {
744 tempToken = TokenNamedoubleCAST;
750 // object string double
751 if ((data[index] == 'o') && (data[++index] == 'b')
752 && (data[++index] == 'j') && (data[++index] == 'e')
753 && (data[++index] == 'c') && (data[++index] == 't')) {
755 tempToken = TokenNameobjectCAST;
758 if ((data[index] == 's') && (data[++index] == 't')
759 && (data[++index] == 'r') && (data[++index] == 'i')
760 && (data[++index] == 'n') && (data[++index] == 'g')) {
762 tempToken = TokenNamestringCAST;
765 if ((data[index] == 'd') && (data[++index] == 'o')
766 && (data[++index] == 'u') && (data[++index] == 'b')
767 && (data[++index] == 'l') && (data[++index] == 'e')) {
769 tempToken = TokenNamedoubleCAST;
776 if ((data[index] == 'b') && (data[++index] == 'o')
777 && (data[++index] == 'o') && (data[++index] == 'l')
778 && (data[++index] == 'e') && (data[++index] == 'a')
779 && (data[++index] == 'n')) {
781 tempToken = TokenNameboolCAST;
784 if ((data[index] == 'i') && (data[++index] == 'n')
785 && (data[++index] == 't') && (data[++index] == 'e')
786 && (data[++index] == 'g') && (data[++index] == 'e')
787 && (data[++index] == 'r')) {
789 tempToken = TokenNameintCAST;
795 while (currentCharacter == ' ' || currentCharacter == '\t') {
796 currentCharacter = source[currentPosition++];
798 if (currentCharacter == ')') {
803 } catch (IndexOutOfBoundsException e) {
805 currentCharacter = tempCharacter;
806 currentPosition = tempPosition;
807 return TokenNameLPAREN;
809 public void consumeStringInterpolated() throws InvalidInputException {
811 // consume next character
812 unicodeAsBackSlash = false;
813 currentCharacter = source[currentPosition++];
814 // if (((currentCharacter = source[currentPosition++]) == '\\')
815 // && (source[currentPosition] == 'u')) {
816 // getNextUnicodeChar();
818 // if (withoutUnicodePtr != 0) {
819 // withoutUnicodeBuffer[++withoutUnicodePtr] =
823 while (currentCharacter != '`') {
824 /** ** in PHP \r and \n are valid in string literals *** */
825 // if ((currentCharacter == '\n')
826 // || (currentCharacter == '\r')) {
827 // // relocate if finding another quote fairly close: thus unicode
828 // '/u000D' will be fully consumed
829 // for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
830 // if (currentPosition + lookAhead == source.length)
832 // if (source[currentPosition + lookAhead] == '\n')
834 // if (source[currentPosition + lookAhead] == '\"') {
835 // currentPosition += lookAhead + 1;
839 // throw new InvalidInputException(INVALID_CHAR_IN_STRING);
841 if (currentCharacter == '\\') {
842 int escapeSize = currentPosition;
843 boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
844 //scanEscapeCharacter make a side effect on this value and we need
845 // the previous value few lines down this one
846 scanDoubleQuotedEscapeCharacter();
847 escapeSize = currentPosition - escapeSize;
848 if (withoutUnicodePtr == 0) {
849 //buffer all the entries that have been left aside....
850 withoutUnicodePtr = currentPosition - escapeSize - 1
852 System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1,
854 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
855 } else { //overwrite the / in the buffer
856 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
857 if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
858 // where only one is correct
863 // consume next character
864 unicodeAsBackSlash = false;
865 currentCharacter = source[currentPosition++];
866 // if (((currentCharacter = source[currentPosition++]) == '\\')
867 // && (source[currentPosition] == 'u')) {
868 // getNextUnicodeChar();
870 if (withoutUnicodePtr != 0) {
871 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
875 } catch (IndexOutOfBoundsException e) {
876 throw new InvalidInputException(UNTERMINATED_STRING);
877 } catch (InvalidInputException e) {
878 if (e.getMessage().equals(INVALID_ESCAPE)) {
879 // relocate if finding another quote fairly close: thus unicode
880 // '/u000D' will be fully consumed
881 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
882 if (currentPosition + lookAhead == source.length)
884 if (source[currentPosition + lookAhead] == '\n')
886 if (source[currentPosition + lookAhead] == '`') {
887 currentPosition += lookAhead + 1;
894 if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
895 // //$NON-NLS-?$ where ? is an
897 if (currentLine == null) {
898 currentLine = new NLSLine();
899 lines.add(currentLine);
901 currentLine.add(new StringLiteral(getCurrentTokenSourceString(),
902 startPosition, currentPosition - 1));
905 public void consumeStringConstant() throws InvalidInputException {
907 // consume next character
908 unicodeAsBackSlash = false;
909 currentCharacter = source[currentPosition++];
910 // if (((currentCharacter = source[currentPosition++]) == '\\')
911 // && (source[currentPosition] == 'u')) {
912 // getNextUnicodeChar();
914 // if (withoutUnicodePtr != 0) {
915 // withoutUnicodeBuffer[++withoutUnicodePtr] =
919 while (currentCharacter != '\'') {
920 /** ** in PHP \r and \n are valid in string literals *** */
921 // if ((currentCharacter == '\n')
922 // || (currentCharacter == '\r')) {
923 // // relocate if finding another quote fairly close: thus unicode
924 // '/u000D' will be fully consumed
925 // for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
926 // if (currentPosition + lookAhead == source.length)
928 // if (source[currentPosition + lookAhead] == '\n')
930 // if (source[currentPosition + lookAhead] == '\"') {
931 // currentPosition += lookAhead + 1;
935 // throw new InvalidInputException(INVALID_CHAR_IN_STRING);
937 if (currentCharacter == '\\') {
938 int escapeSize = currentPosition;
939 boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
940 //scanEscapeCharacter make a side effect on this value and we need
941 // the previous value few lines down this one
942 scanSingleQuotedEscapeCharacter();
943 escapeSize = currentPosition - escapeSize;
944 if (withoutUnicodePtr == 0) {
945 //buffer all the entries that have been left aside....
946 withoutUnicodePtr = currentPosition - escapeSize - 1
948 System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1,
950 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
951 } else { //overwrite the / in the buffer
952 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
953 if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
954 // where only one is correct
959 // consume next character
960 unicodeAsBackSlash = false;
961 currentCharacter = source[currentPosition++];
962 // if (((currentCharacter = source[currentPosition++]) == '\\')
963 // && (source[currentPosition] == 'u')) {
964 // getNextUnicodeChar();
966 if (withoutUnicodePtr != 0) {
967 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
971 } catch (IndexOutOfBoundsException e) {
972 throw new InvalidInputException(UNTERMINATED_STRING);
973 } catch (InvalidInputException e) {
974 if (e.getMessage().equals(INVALID_ESCAPE)) {
975 // relocate if finding another quote fairly close: thus unicode
976 // '/u000D' will be fully consumed
977 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
978 if (currentPosition + lookAhead == source.length)
980 if (source[currentPosition + lookAhead] == '\n')
982 if (source[currentPosition + lookAhead] == '\'') {
983 currentPosition += lookAhead + 1;
990 if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
991 // //$NON-NLS-?$ where ? is an
993 if (currentLine == null) {
994 currentLine = new NLSLine();
995 lines.add(currentLine);
997 currentLine.add(new StringLiteral(getCurrentTokenSourceString(),
998 startPosition, currentPosition - 1));
1001 public void consumeStringLiteral() throws InvalidInputException {
1003 // consume next character
1004 unicodeAsBackSlash = false;
1005 currentCharacter = source[currentPosition++];
1006 // if (((currentCharacter = source[currentPosition++]) == '\\')
1007 // && (source[currentPosition] == 'u')) {
1008 // getNextUnicodeChar();
1010 // if (withoutUnicodePtr != 0) {
1011 // withoutUnicodeBuffer[++withoutUnicodePtr] =
1012 // currentCharacter;
1015 while (currentCharacter != '"') {
1016 /** ** in PHP \r and \n are valid in string literals *** */
1017 // if ((currentCharacter == '\n')
1018 // || (currentCharacter == '\r')) {
1019 // // relocate if finding another quote fairly close: thus unicode
1020 // '/u000D' will be fully consumed
1021 // for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1022 // if (currentPosition + lookAhead == source.length)
1024 // if (source[currentPosition + lookAhead] == '\n')
1026 // if (source[currentPosition + lookAhead] == '\"') {
1027 // currentPosition += lookAhead + 1;
1031 // throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1033 if (currentCharacter == '\\') {
1034 int escapeSize = currentPosition;
1035 boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
1036 //scanEscapeCharacter make a side effect on this value and we need
1037 // the previous value few lines down this one
1038 scanDoubleQuotedEscapeCharacter();
1039 escapeSize = currentPosition - escapeSize;
1040 if (withoutUnicodePtr == 0) {
1041 //buffer all the entries that have been left aside....
1042 withoutUnicodePtr = currentPosition - escapeSize - 1
1044 System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1,
1046 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1047 } else { //overwrite the / in the buffer
1048 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
1049 if (backSlashAsUnicodeInString) { //there are TWO \ in the stream
1050 // where only one is correct
1051 withoutUnicodePtr--;
1055 // consume next character
1056 unicodeAsBackSlash = false;
1057 currentCharacter = source[currentPosition++];
1058 // if (((currentCharacter = source[currentPosition++]) == '\\')
1059 // && (source[currentPosition] == 'u')) {
1060 // getNextUnicodeChar();
1062 if (withoutUnicodePtr != 0) {
1063 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1067 } catch (IndexOutOfBoundsException e) {
1068 throw new InvalidInputException(UNTERMINATED_STRING);
1069 } catch (InvalidInputException e) {
1070 if (e.getMessage().equals(INVALID_ESCAPE)) {
1071 // relocate if finding another quote fairly close: thus unicode
1072 // '/u000D' will be fully consumed
1073 for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1074 if (currentPosition + lookAhead == source.length)
1076 if (source[currentPosition + lookAhead] == '\n')
1078 if (source[currentPosition + lookAhead] == '\"') {
1079 currentPosition += lookAhead + 1;
1086 if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags
1087 // //$NON-NLS-?$ where ? is an
1089 if (currentLine == null) {
1090 currentLine = new NLSLine();
1091 lines.add(currentLine);
1093 currentLine.add(new StringLiteral(getCurrentTokenSourceString(),
1094 startPosition, currentPosition - 1));
1097 public int getNextToken() throws InvalidInputException {
1099 return getInlinedHTML(currentPosition);
1102 this.wasAcr = false;
1104 jumpOverMethodBody();
1106 return currentPosition > source.length ? TokenNameEOF : TokenNameRBRACE;
1110 withoutUnicodePtr = 0;
1111 //start with a new token
1112 char encapsedChar = ' ';
1113 if (!encapsedStringStack.isEmpty()) {
1114 encapsedChar = ((Character) encapsedStringStack.peek()).charValue();
1116 if (encapsedChar != '$' && encapsedChar != ' ') {
1117 currentCharacter = source[currentPosition++];
1118 if (currentCharacter == encapsedChar) {
1119 switch (currentCharacter) {
1121 return TokenNameEncapsedString0;
1123 return TokenNameEncapsedString1;
1125 return TokenNameEncapsedString2;
1128 while (currentCharacter != encapsedChar) {
1129 /** ** in PHP \r and \n are valid in string literals *** */
1130 switch (currentCharacter) {
1132 int escapeSize = currentPosition;
1133 boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
1134 //scanEscapeCharacter make a side effect on this value and
1135 // we need the previous value few lines down this one
1136 scanDoubleQuotedEscapeCharacter();
1137 escapeSize = currentPosition - escapeSize;
1138 if (withoutUnicodePtr == 0) {
1139 //buffer all the entries that have been left aside....
1140 withoutUnicodePtr = currentPosition - escapeSize - 1
1142 System.arraycopy(source, startPosition,
1143 withoutUnicodeBuffer, 1, withoutUnicodePtr);
1144 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1145 } else { //overwrite the / in the buffer
1146 withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
1147 if (backSlashAsUnicodeInString) { //there are TWO \ in
1148 withoutUnicodePtr--;
1153 if (isPHPIdentifierStart(source[currentPosition])
1154 || source[currentPosition] == '{') {
1156 encapsedStringStack.push(new Character('$'));
1157 return TokenNameSTRING;
1161 if (source[currentPosition] == '$') { // CURLY_OPEN
1163 encapsedStringStack.push(new Character('$'));
1164 return TokenNameSTRING;
1167 // consume next character
1168 unicodeAsBackSlash = false;
1169 currentCharacter = source[currentPosition++];
1170 if (withoutUnicodePtr != 0) {
1171 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1176 return TokenNameSTRING;
1178 // ---------Consume white space and handles startPosition---------
1179 int whiteStart = currentPosition;
1180 startPosition = currentPosition;
1181 currentCharacter = source[currentPosition++];
1182 if (encapsedChar == '$') {
1183 switch (currentCharacter) {
1185 currentCharacter = source[currentPosition++];
1186 return TokenNameSTRING;
1188 if (encapsedChar == '$') {
1189 if (getNextChar('$'))
1190 return TokenNameCURLY_OPEN;
1192 return TokenNameLBRACE;
1194 return TokenNameRBRACE;
1196 return TokenNameLBRACKET;
1198 return TokenNameRBRACKET;
1200 if (tokenizeStrings) {
1201 consumeStringConstant();
1202 return TokenNameStringConstant;
1204 return TokenNameEncapsedString1;
1206 return TokenNameEncapsedString2;
1208 if (tokenizeStrings) {
1209 consumeStringInterpolated();
1210 return TokenNameStringInterpolated;
1212 return TokenNameEncapsedString0;
1214 if (getNextChar('>'))
1215 return TokenNameMINUS_GREATER;
1216 return TokenNameSTRING;
1218 if (currentCharacter == '$') {
1219 int oldPosition = currentPosition;
1221 currentCharacter = source[currentPosition++];
1222 if (currentCharacter == '{') {
1223 return TokenNameDOLLAR_LBRACE;
1225 if (isPHPIdentifierStart(currentCharacter)) {
1226 return scanIdentifierOrKeyword(true);
1228 currentPosition = oldPosition;
1229 return TokenNameSTRING;
1231 } catch (IndexOutOfBoundsException e) {
1232 currentPosition = oldPosition;
1233 return TokenNameSTRING;
1236 if (isPHPIdentifierStart(currentCharacter))
1237 return scanIdentifierOrKeyword(false);
1238 if (Character.isDigit(currentCharacter))
1239 return scanNumber(false);
1240 return TokenNameERROR;
1243 // boolean isWhiteSpace;
1244 while ((currentCharacter == ' ')
1245 || Character.isWhitespace(currentCharacter)) {
1246 startPosition = currentPosition;
1247 currentCharacter = source[currentPosition++];
1248 // if (((currentCharacter = source[currentPosition++]) == '\\')
1249 // && (source[currentPosition] == 'u')) {
1250 // isWhiteSpace = jumpOverUnicodeWhiteSpace();
1252 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1253 checkNonExternalizeString();
1254 if (recordLineSeparator) {
1255 pushLineSeparator();
1260 // isWhiteSpace = (currentCharacter == ' ')
1261 // || Character.isWhitespace(currentCharacter);
1264 if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) {
1265 // reposition scanner in case we are interested by spaces as tokens
1267 startPosition = whiteStart;
1268 return TokenNameWHITESPACE;
1270 //little trick to get out in the middle of a source compuation
1271 if (currentPosition > eofPosition)
1272 return TokenNameEOF;
1273 // ---------Identify the next token-------------
1274 switch (currentCharacter) {
1276 return getCastOrParen();
1278 return TokenNameRPAREN;
1280 return TokenNameLBRACE;
1282 return TokenNameRBRACE;
1284 return TokenNameLBRACKET;
1286 return TokenNameRBRACKET;
1288 return TokenNameSEMICOLON;
1290 return TokenNameCOMMA;
1292 if (getNextChar('='))
1293 return TokenNameDOT_EQUAL;
1294 if (getNextCharAsDigit())
1295 return scanNumber(true);
1296 return TokenNameDOT;
1300 if ((test = getNextChar('+', '=')) == 0)
1301 return TokenNamePLUS_PLUS;
1303 return TokenNamePLUS_EQUAL;
1304 return TokenNamePLUS;
1309 if ((test = getNextChar('-', '=')) == 0)
1310 return TokenNameMINUS_MINUS;
1312 return TokenNameMINUS_EQUAL;
1313 if (getNextChar('>'))
1314 return TokenNameMINUS_GREATER;
1315 return TokenNameMINUS;
1318 if (getNextChar('='))
1319 return TokenNameTWIDDLE_EQUAL;
1320 return TokenNameTWIDDLE;
1322 if (getNextChar('=')) {
1323 if (getNextChar('=')) {
1324 return TokenNameNOT_EQUAL_EQUAL;
1326 return TokenNameNOT_EQUAL;
1328 return TokenNameNOT;
1330 if (getNextChar('='))
1331 return TokenNameMULTIPLY_EQUAL;
1332 return TokenNameMULTIPLY;
1334 if (getNextChar('='))
1335 return TokenNameREMAINDER_EQUAL;
1336 return TokenNameREMAINDER;
1339 int oldPosition = currentPosition;
1341 currentCharacter = source[currentPosition++];
1342 } catch (IndexOutOfBoundsException e) {
1343 currentPosition = oldPosition;
1344 return TokenNameLESS;
1346 switch (currentCharacter) {
1348 return TokenNameLESS_EQUAL;
1350 return TokenNameNOT_EQUAL;
1352 if (getNextChar('='))
1353 return TokenNameLEFT_SHIFT_EQUAL;
1354 if (getNextChar('<')) {
1355 currentCharacter = source[currentPosition++];
1356 while (Character.isWhitespace(currentCharacter)) {
1357 currentCharacter = source[currentPosition++];
1359 int heredocStart = currentPosition - 1;
1360 int heredocLength = 0;
1361 if (isPHPIdentifierStart(currentCharacter)) {
1362 currentCharacter = source[currentPosition++];
1364 return TokenNameERROR;
1366 while (isPHPIdentifierPart(currentCharacter)) {
1367 currentCharacter = source[currentPosition++];
1369 heredocLength = currentPosition - heredocStart - 1;
1370 // heredoc end-tag determination
1371 boolean endTag = true;
1374 ch = source[currentPosition++];
1375 if (ch == '\r' || ch == '\n') {
1376 if (recordLineSeparator) {
1377 pushLineSeparator();
1381 for (int i = 0; i < heredocLength; i++) {
1382 if (source[currentPosition + i] != source[heredocStart
1389 currentPosition += heredocLength - 1;
1390 currentCharacter = source[currentPosition++];
1391 break; // do...while loop
1397 return TokenNameHEREDOC;
1399 return TokenNameLEFT_SHIFT;
1401 currentPosition = oldPosition;
1402 return TokenNameLESS;
1407 if ((test = getNextChar('=', '>')) == 0)
1408 return TokenNameGREATER_EQUAL;
1410 if ((test = getNextChar('=', '>')) == 0)
1411 return TokenNameRIGHT_SHIFT_EQUAL;
1412 return TokenNameRIGHT_SHIFT;
1414 return TokenNameGREATER;
1417 if (getNextChar('=')) {
1418 if (getNextChar('=')) {
1419 return TokenNameEQUAL_EQUAL_EQUAL;
1421 return TokenNameEQUAL_EQUAL;
1423 if (getNextChar('>'))
1424 return TokenNameEQUAL_GREATER;
1425 return TokenNameEQUAL;
1429 if ((test = getNextChar('&', '=')) == 0)
1430 return TokenNameAND_AND;
1432 return TokenNameAND_EQUAL;
1433 return TokenNameAND;
1438 if ((test = getNextChar('|', '=')) == 0)
1439 return TokenNameOR_OR;
1441 return TokenNameOR_EQUAL;
1445 if (getNextChar('='))
1446 return TokenNameXOR_EQUAL;
1447 return TokenNameXOR;
1449 if (getNextChar('>')) {
1451 if (currentPosition == source.length) {
1453 return TokenNameINLINE_HTML;
1455 return getInlinedHTML(currentPosition - 2);
1457 return TokenNameQUESTION;
1459 if (getNextChar(':'))
1460 return TokenNamePAAMAYIM_NEKUDOTAYIM;
1461 return TokenNameCOLON;
1465 consumeStringConstant();
1466 return TokenNameStringConstant;
1468 if (tokenizeStrings) {
1469 consumeStringLiteral();
1470 return TokenNameStringLiteral;
1472 return TokenNameEncapsedString2;
1474 if (tokenizeStrings) {
1475 consumeStringInterpolated();
1476 return TokenNameStringInterpolated;
1478 return TokenNameEncapsedString0;
1482 char startChar = currentCharacter;
1483 if (getNextChar('=')) {
1484 return TokenNameDIVIDE_EQUAL;
1487 if ((startChar == '#') || (test = getNextChar('/', '*')) == 0) {
1489 int endPositionForLineComment = 0;
1490 try { //get the next char
1491 currentCharacter = source[currentPosition++];
1492 // if (((currentCharacter = source[currentPosition++])
1494 // && (source[currentPosition] == 'u')) {
1495 // //-------------unicode traitement ------------
1496 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1497 // currentPosition++;
1498 // while (source[currentPosition] == 'u') {
1499 // currentPosition++;
1502 // Character.getNumericValue(source[currentPosition++]))
1506 // Character.getNumericValue(source[currentPosition++]))
1510 // Character.getNumericValue(source[currentPosition++]))
1514 // Character.getNumericValue(source[currentPosition++]))
1518 // InvalidInputException(INVALID_UNICODE_ESCAPE);
1520 // currentCharacter =
1521 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1524 //handle the \\u case manually into comment
1525 // if (currentCharacter == '\\') {
1526 // if (source[currentPosition] == '\\')
1527 // currentPosition++;
1528 // } //jump over the \\
1529 boolean isUnicode = false;
1530 while (currentCharacter != '\r' && currentCharacter != '\n') {
1531 if (currentCharacter == '?') {
1532 if (getNextChar('>')) {
1533 startPosition = currentPosition - 2;
1535 return TokenNameINLINE_HTML;
1540 currentCharacter = source[currentPosition++];
1541 // if (((currentCharacter = source[currentPosition++])
1543 // && (source[currentPosition] == 'u')) {
1544 // isUnicode = true;
1545 // //-------------unicode traitement ------------
1546 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1547 // currentPosition++;
1548 // while (source[currentPosition] == 'u') {
1549 // currentPosition++;
1552 // Character.getNumericValue(source[currentPosition++]))
1556 // Character.getNumericValue(
1557 // source[currentPosition++]))
1561 // Character.getNumericValue(
1562 // source[currentPosition++]))
1566 // Character.getNumericValue(
1567 // source[currentPosition++]))
1571 // InvalidInputException(INVALID_UNICODE_ESCAPE);
1573 // currentCharacter =
1574 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1577 //handle the \\u case manually into comment
1578 // if (currentCharacter == '\\') {
1579 // if (source[currentPosition] == '\\')
1580 // currentPosition++;
1581 // } //jump over the \\
1584 endPositionForLineComment = currentPosition - 6;
1586 endPositionForLineComment = currentPosition - 1;
1588 recordComment(false);
1589 if ((currentCharacter == '\r')
1590 || (currentCharacter == '\n')) {
1591 checkNonExternalizeString();
1592 if (recordLineSeparator) {
1594 pushUnicodeLineSeparator();
1596 pushLineSeparator();
1602 if (tokenizeComments) {
1604 currentPosition = endPositionForLineComment;
1605 // reset one character behind
1607 return TokenNameCOMMENT_LINE;
1609 } catch (IndexOutOfBoundsException e) { //an eof will them
1611 if (tokenizeComments) {
1613 // reset one character behind
1614 return TokenNameCOMMENT_LINE;
1620 //traditional and annotation comment
1621 boolean isJavadoc = false, star = false;
1622 // consume next character
1623 unicodeAsBackSlash = false;
1624 currentCharacter = source[currentPosition++];
1625 // if (((currentCharacter = source[currentPosition++]) ==
1627 // && (source[currentPosition] == 'u')) {
1628 // getNextUnicodeChar();
1630 // if (withoutUnicodePtr != 0) {
1631 // withoutUnicodeBuffer[++withoutUnicodePtr] =
1632 // currentCharacter;
1635 if (currentCharacter == '*') {
1639 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1640 checkNonExternalizeString();
1641 if (recordLineSeparator) {
1642 pushLineSeparator();
1647 try { //get the next char
1648 currentCharacter = source[currentPosition++];
1649 // if (((currentCharacter = source[currentPosition++])
1651 // && (source[currentPosition] == 'u')) {
1652 // //-------------unicode traitement ------------
1653 // getNextUnicodeChar();
1655 //handle the \\u case manually into comment
1656 // if (currentCharacter == '\\') {
1657 // if (source[currentPosition] == '\\')
1658 // currentPosition++;
1659 // //jump over the \\
1661 // empty comment is not a javadoc /**/
1662 if (currentCharacter == '/') {
1665 //loop until end of comment */
1666 while ((currentCharacter != '/') || (!star)) {
1667 if ((currentCharacter == '\r')
1668 || (currentCharacter == '\n')) {
1669 checkNonExternalizeString();
1670 if (recordLineSeparator) {
1671 pushLineSeparator();
1676 star = currentCharacter == '*';
1678 currentCharacter = source[currentPosition++];
1679 // if (((currentCharacter = source[currentPosition++])
1681 // && (source[currentPosition] == 'u')) {
1682 // //-------------unicode traitement ------------
1683 // getNextUnicodeChar();
1685 //handle the \\u case manually into comment
1686 // if (currentCharacter == '\\') {
1687 // if (source[currentPosition] == '\\')
1688 // currentPosition++;
1689 // } //jump over the \\
1691 recordComment(isJavadoc);
1692 if (tokenizeComments) {
1694 return TokenNameCOMMENT_PHPDOC;
1695 return TokenNameCOMMENT_BLOCK;
1697 } catch (IndexOutOfBoundsException e) {
1698 throw new InvalidInputException(UNTERMINATED_COMMENT);
1702 return TokenNameDIVIDE;
1706 return TokenNameEOF;
1707 //the atEnd may not be <currentPosition == source.length> if
1708 // source is only some part of a real (external) stream
1709 throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
1711 if (currentCharacter == '$') {
1712 int oldPosition = currentPosition;
1714 currentCharacter = source[currentPosition++];
1715 if (isPHPIdentifierStart(currentCharacter)) {
1716 return scanIdentifierOrKeyword(true);
1718 currentPosition = oldPosition;
1719 return TokenNameDOLLAR;
1721 } catch (IndexOutOfBoundsException e) {
1722 currentPosition = oldPosition;
1723 return TokenNameDOLLAR;
1726 if (isPHPIdentifierStart(currentCharacter))
1727 return scanIdentifierOrKeyword(false);
1728 if (Character.isDigit(currentCharacter))
1729 return scanNumber(false);
1730 return TokenNameERROR;
1733 } //-----------------end switch while try--------------------
1734 catch (IndexOutOfBoundsException e) {
1737 return TokenNameEOF;
1741 * InvalidInputException
1743 private int getInlinedHTML(int start) throws InvalidInputException {
1744 // int htmlPosition = start;
1745 if (currentPosition > source.length) {
1746 currentPosition = source.length;
1747 return TokenNameEOF;
1749 startPosition = start;
1752 currentCharacter = source[currentPosition++];
1753 if (currentCharacter == '<') {
1754 if (getNextChar('?')) {
1755 currentCharacter = source[currentPosition++];
1756 if ((currentCharacter == ' ')
1757 || Character.isWhitespace(currentCharacter)) {
1760 return TokenNameINLINE_HTML;
1762 boolean phpStart = (currentCharacter == 'P')
1763 || (currentCharacter == 'p');
1765 int test = getNextChar('H', 'h');
1767 test = getNextChar('P', 'p');
1771 return TokenNameINLINE_HTML;
1778 if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
1779 if (recordLineSeparator) {
1780 pushLineSeparator();
1785 } //-----------------while--------------------
1787 return TokenNameINLINE_HTML;
1788 } //-----------------try--------------------
1789 catch (IndexOutOfBoundsException e) {
1790 startPosition = start;
1794 return TokenNameINLINE_HTML;
1796 // public final void getNextUnicodeChar()
1797 // throws IndexOutOfBoundsException, InvalidInputException {
1799 // //handle the case of unicode.
1800 // //when a unicode appears then we must use a buffer that holds char
1802 // //At the end of this method currentCharacter holds the new visited char
1803 // //and currentPosition points right next after it
1805 // //ALL getNextChar.... ARE OPTIMIZED COPIES
1807 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
1808 // currentPosition++;
1809 // while (source[currentPosition] == 'u') {
1810 // currentPosition++;
1814 // if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
1816 // || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
1818 // || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
1820 // || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
1822 // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
1824 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1825 // //need the unicode buffer
1826 // if (withoutUnicodePtr == 0) {
1827 // //buffer all the entries that have been left aside....
1828 // withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
1829 // System.arraycopy(
1832 // withoutUnicodeBuffer,
1834 // withoutUnicodePtr);
1836 // //fill the buffer with the char
1837 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1839 // unicodeAsBackSlash = currentCharacter == '\\';
1842 * Tokenize a method body, assuming that curly brackets are properly
1845 public final void jumpOverMethodBody() {
1846 this.wasAcr = false;
1849 while (true) { //loop for jumping over comments
1850 // ---------Consume white space and handles startPosition---------
1851 boolean isWhiteSpace;
1853 startPosition = currentPosition;
1854 currentCharacter = source[currentPosition++];
1855 // if (((currentCharacter = source[currentPosition++]) == '\\')
1856 // && (source[currentPosition] == 'u')) {
1857 // isWhiteSpace = jumpOverUnicodeWhiteSpace();
1859 if (recordLineSeparator
1860 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
1861 pushLineSeparator();
1862 isWhiteSpace = Character.isWhitespace(currentCharacter);
1864 } while (isWhiteSpace);
1865 // -------consume token until } is found---------
1866 switch (currentCharacter) {
1878 test = getNextChar('\\');
1881 scanDoubleQuotedEscapeCharacter();
1882 } catch (InvalidInputException ex) {
1885 // try { // consume next character
1886 unicodeAsBackSlash = false;
1887 currentCharacter = source[currentPosition++];
1888 // if (((currentCharacter = source[currentPosition++]) == '\\')
1889 // && (source[currentPosition] == 'u')) {
1890 // getNextUnicodeChar();
1892 if (withoutUnicodePtr != 0) {
1893 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1896 // } catch (InvalidInputException ex) {
1904 // try { // consume next character
1905 unicodeAsBackSlash = false;
1906 currentCharacter = source[currentPosition++];
1907 // if (((currentCharacter = source[currentPosition++]) == '\\')
1908 // && (source[currentPosition] == 'u')) {
1909 // getNextUnicodeChar();
1911 if (withoutUnicodePtr != 0) {
1912 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1915 // } catch (InvalidInputException ex) {
1917 while (currentCharacter != '"') {
1918 if (currentCharacter == '\r') {
1919 if (source[currentPosition] == '\n')
1922 // the string cannot go further that the line
1924 if (currentCharacter == '\n') {
1926 // the string cannot go further that the line
1928 if (currentCharacter == '\\') {
1930 scanDoubleQuotedEscapeCharacter();
1931 } catch (InvalidInputException ex) {
1934 // try { // consume next character
1935 unicodeAsBackSlash = false;
1936 currentCharacter = source[currentPosition++];
1937 // if (((currentCharacter = source[currentPosition++]) == '\\')
1938 // && (source[currentPosition] == 'u')) {
1939 // getNextUnicodeChar();
1941 if (withoutUnicodePtr != 0) {
1942 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
1945 // } catch (InvalidInputException ex) {
1948 } catch (IndexOutOfBoundsException e) {
1955 if ((test = getNextChar('/', '*')) == 0) {
1959 currentCharacter = source[currentPosition++];
1960 // if (((currentCharacter = source[currentPosition++]) ==
1962 // && (source[currentPosition] == 'u')) {
1963 // //-------------unicode traitement ------------
1964 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
1965 // currentPosition++;
1966 // while (source[currentPosition] == 'u') {
1967 // currentPosition++;
1970 // Character.getNumericValue(source[currentPosition++]))
1974 // Character.getNumericValue(source[currentPosition++]))
1978 // Character.getNumericValue(source[currentPosition++]))
1982 // Character.getNumericValue(source[currentPosition++]))
1985 // //error don't care of the value
1986 // currentCharacter = 'A';
1987 // } //something different from \n and \r
1989 // currentCharacter =
1990 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
1993 while (currentCharacter != '\r' && currentCharacter != '\n') {
1995 currentCharacter = source[currentPosition++];
1996 // if (((currentCharacter = source[currentPosition++])
1998 // && (source[currentPosition] == 'u')) {
1999 // //-------------unicode traitement ------------
2000 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2001 // currentPosition++;
2002 // while (source[currentPosition] == 'u') {
2003 // currentPosition++;
2006 // Character.getNumericValue(source[currentPosition++]))
2010 // Character.getNumericValue(source[currentPosition++]))
2014 // Character.getNumericValue(source[currentPosition++]))
2018 // Character.getNumericValue(source[currentPosition++]))
2021 // //error don't care of the value
2022 // currentCharacter = 'A';
2023 // } //something different from \n and \r
2025 // currentCharacter =
2026 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2030 if (recordLineSeparator
2031 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2032 pushLineSeparator();
2033 } catch (IndexOutOfBoundsException e) {
2034 } //an eof will them be generated
2038 //traditional and annotation comment
2039 boolean star = false;
2040 // try { // consume next character
2041 unicodeAsBackSlash = false;
2042 currentCharacter = source[currentPosition++];
2043 // if (((currentCharacter = source[currentPosition++]) == '\\')
2044 // && (source[currentPosition] == 'u')) {
2045 // getNextUnicodeChar();
2047 if (withoutUnicodePtr != 0) {
2048 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2051 // } catch (InvalidInputException ex) {
2053 if (currentCharacter == '*') {
2056 if (recordLineSeparator
2057 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2058 pushLineSeparator();
2059 try { //get the next char
2060 currentCharacter = source[currentPosition++];
2061 // if (((currentCharacter = source[currentPosition++]) ==
2063 // && (source[currentPosition] == 'u')) {
2064 // //-------------unicode traitement ------------
2065 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2066 // currentPosition++;
2067 // while (source[currentPosition] == 'u') {
2068 // currentPosition++;
2071 // Character.getNumericValue(source[currentPosition++]))
2075 // Character.getNumericValue(source[currentPosition++]))
2079 // Character.getNumericValue(source[currentPosition++]))
2083 // Character.getNumericValue(source[currentPosition++]))
2086 // //error don't care of the value
2087 // currentCharacter = 'A';
2088 // } //something different from * and /
2090 // currentCharacter =
2091 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2094 //loop until end of comment */
2095 while ((currentCharacter != '/') || (!star)) {
2096 if (recordLineSeparator
2097 && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2098 pushLineSeparator();
2099 star = currentCharacter == '*';
2101 currentCharacter = source[currentPosition++];
2102 // if (((currentCharacter = source[currentPosition++])
2104 // && (source[currentPosition] == 'u')) {
2105 // //-------------unicode traitement ------------
2106 // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2107 // currentPosition++;
2108 // while (source[currentPosition] == 'u') {
2109 // currentPosition++;
2112 // Character.getNumericValue(source[currentPosition++]))
2116 // Character.getNumericValue(source[currentPosition++]))
2120 // Character.getNumericValue(source[currentPosition++]))
2124 // Character.getNumericValue(source[currentPosition++]))
2127 // //error don't care of the value
2128 // currentCharacter = 'A';
2129 // } //something different from * and /
2131 // currentCharacter =
2132 // (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2136 } catch (IndexOutOfBoundsException e) {
2144 if (isPHPIdentifierStart(currentCharacter)
2145 || currentCharacter == '$') {
2147 scanIdentifierOrKeyword((currentCharacter == '$'));
2148 } catch (InvalidInputException ex) {
2152 if (Character.isDigit(currentCharacter)) {
2155 } catch (InvalidInputException ex) {
2161 //-----------------end switch while try--------------------
2162 } catch (IndexOutOfBoundsException e) {
2163 } catch (InvalidInputException e) {
2167 // public final boolean jumpOverUnicodeWhiteSpace()
2168 // throws InvalidInputException {
2170 // //handle the case of unicode. Jump over the next whiteSpace
2171 // //making startPosition pointing on the next available char
2172 // //On false, the currentCharacter is filled up with a potential
2176 // this.wasAcr = false;
2177 // int c1, c2, c3, c4;
2178 // int unicodeSize = 6;
2179 // currentPosition++;
2180 // while (source[currentPosition] == 'u') {
2181 // currentPosition++;
2185 // if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
2187 // || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15
2189 // || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15
2191 // || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15
2193 // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
2196 // currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
2197 // if (recordLineSeparator
2198 // && ((currentCharacter == '\r') || (currentCharacter == '\n')))
2199 // pushLineSeparator();
2200 // if (Character.isWhitespace(currentCharacter))
2203 // //buffer the new char which is not a white space
2204 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2205 // //withoutUnicodePtr == 1 is true here
2207 // } catch (IndexOutOfBoundsException e) {
2208 // throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
2211 public final int[] getLineEnds() {
2212 //return a bounded copy of this.lineEnds
2214 System.arraycopy(lineEnds, 0, copy = new int[linePtr + 1], 0, linePtr + 1);
2217 public char[] getSource() {
2220 final char[] optimizedCurrentTokenSource1() {
2221 //return always the same char[] build only once
2222 //optimization at no speed cost of 99.5 % of the singleCharIdentifier
2223 char charOne = source[startPosition];
2278 return new char[]{charOne};
2281 final char[] optimizedCurrentTokenSource2() {
2282 //try to return the same char[] build only once
2284 int hash = (((c0 = source[startPosition]) << 6) + (c1 = source[startPosition + 1]))
2286 char[][] table = charArray_length[0][hash];
2288 while (++i < InternalTableSize) {
2289 char[] charArray = table[i];
2290 if ((c0 == charArray[0]) && (c1 == charArray[1]))
2293 //---------other side---------
2295 int max = newEntry2;
2296 while (++i <= max) {
2297 char[] charArray = table[i];
2298 if ((c0 == charArray[0]) && (c1 == charArray[1]))
2301 //--------add the entry-------
2302 if (++max >= InternalTableSize)
2305 table[max] = (r = new char[]{c0, c1});
2309 final char[] optimizedCurrentTokenSource3() {
2310 //try to return the same char[] build only once
2312 int hash = (((c0 = source[startPosition]) << 12)
2313 + ((c1 = source[startPosition + 1]) << 6) + (c2 = source[startPosition + 2]))
2315 char[][] table = charArray_length[1][hash];
2317 while (++i < InternalTableSize) {
2318 char[] charArray = table[i];
2319 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
2322 //---------other side---------
2324 int max = newEntry3;
2325 while (++i <= max) {
2326 char[] charArray = table[i];
2327 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
2330 //--------add the entry-------
2331 if (++max >= InternalTableSize)
2334 table[max] = (r = new char[]{c0, c1, c2});
2338 final char[] optimizedCurrentTokenSource4() {
2339 //try to return the same char[] build only once
2340 char c0, c1, c2, c3;
2341 long hash = ((((long) (c0 = source[startPosition])) << 18)
2342 + ((c1 = source[startPosition + 1]) << 12)
2343 + ((c2 = source[startPosition + 2]) << 6) + (c3 = source[startPosition + 3]))
2345 char[][] table = charArray_length[2][(int) hash];
2347 while (++i < InternalTableSize) {
2348 char[] charArray = table[i];
2349 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2350 && (c3 == charArray[3]))
2353 //---------other side---------
2355 int max = newEntry4;
2356 while (++i <= max) {
2357 char[] charArray = table[i];
2358 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2359 && (c3 == charArray[3]))
2362 //--------add the entry-------
2363 if (++max >= InternalTableSize)
2366 table[max] = (r = new char[]{c0, c1, c2, c3});
2370 final char[] optimizedCurrentTokenSource5() {
2371 //try to return the same char[] build only once
2372 char c0, c1, c2, c3, c4;
2373 long hash = ((((long) (c0 = source[startPosition])) << 24)
2374 + (((long) (c1 = source[startPosition + 1])) << 18)
2375 + ((c2 = source[startPosition + 2]) << 12)
2376 + ((c3 = source[startPosition + 3]) << 6) + (c4 = source[startPosition + 4]))
2378 char[][] table = charArray_length[3][(int) hash];
2380 while (++i < InternalTableSize) {
2381 char[] charArray = table[i];
2382 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2383 && (c3 == charArray[3]) && (c4 == charArray[4]))
2386 //---------other side---------
2388 int max = newEntry5;
2389 while (++i <= max) {
2390 char[] charArray = table[i];
2391 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2392 && (c3 == charArray[3]) && (c4 == charArray[4]))
2395 //--------add the entry-------
2396 if (++max >= InternalTableSize)
2399 table[max] = (r = new char[]{c0, c1, c2, c3, c4});
2403 final char[] optimizedCurrentTokenSource6() {
2404 //try to return the same char[] build only once
2405 char c0, c1, c2, c3, c4, c5;
2406 long hash = ((((long) (c0 = source[startPosition])) << 32)
2407 + (((long) (c1 = source[startPosition + 1])) << 24)
2408 + (((long) (c2 = source[startPosition + 2])) << 18)
2409 + ((c3 = source[startPosition + 3]) << 12)
2410 + ((c4 = source[startPosition + 4]) << 6) + (c5 = source[startPosition + 5]))
2412 char[][] table = charArray_length[4][(int) hash];
2414 while (++i < InternalTableSize) {
2415 char[] charArray = table[i];
2416 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2417 && (c3 == charArray[3]) && (c4 == charArray[4])
2418 && (c5 == charArray[5]))
2421 //---------other side---------
2423 int max = newEntry6;
2424 while (++i <= max) {
2425 char[] charArray = table[i];
2426 if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])
2427 && (c3 == charArray[3]) && (c4 == charArray[4])
2428 && (c5 == charArray[5]))
2431 //--------add the entry-------
2432 if (++max >= InternalTableSize)
2435 table[max] = (r = new char[]{c0, c1, c2, c3, c4, c5});
2439 public final void pushLineSeparator() throws InvalidInputException {
2440 //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
2441 final int INCREMENT = 250;
2442 if (this.checkNonExternalizedStringLiterals) {
2443 // reinitialize the current line for non externalize strings purpose
2446 //currentCharacter is at position currentPosition-1
2448 if (currentCharacter == '\r') {
2449 int separatorPos = currentPosition - 1;
2450 if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2452 //System.out.println("CR-" + separatorPos);
2454 lineEnds[++linePtr] = separatorPos;
2455 } catch (IndexOutOfBoundsException e) {
2456 //linePtr value is correct
2457 int oldLength = lineEnds.length;
2458 int[] old = lineEnds;
2459 lineEnds = new int[oldLength + INCREMENT];
2460 System.arraycopy(old, 0, lineEnds, 0, oldLength);
2461 lineEnds[linePtr] = separatorPos;
2463 // look-ahead for merged cr+lf
2465 if (source[currentPosition] == '\n') {
2466 //System.out.println("look-ahead LF-" + currentPosition);
2467 lineEnds[linePtr] = currentPosition;
2473 } catch (IndexOutOfBoundsException e) {
2478 if (currentCharacter == '\n') {
2479 //must merge eventual cr followed by lf
2480 if (wasAcr && (lineEnds[linePtr] == (currentPosition - 2))) {
2481 //System.out.println("merge LF-" + (currentPosition - 1));
2482 lineEnds[linePtr] = currentPosition - 1;
2484 int separatorPos = currentPosition - 1;
2485 if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2487 // System.out.println("LF-" + separatorPos);
2489 lineEnds[++linePtr] = separatorPos;
2490 } catch (IndexOutOfBoundsException e) {
2491 //linePtr value is correct
2492 int oldLength = lineEnds.length;
2493 int[] old = lineEnds;
2494 lineEnds = new int[oldLength + INCREMENT];
2495 System.arraycopy(old, 0, lineEnds, 0, oldLength);
2496 lineEnds[linePtr] = separatorPos;
2503 public final void pushUnicodeLineSeparator() {
2504 // isUnicode means that the \r or \n has been read as a unicode character
2505 //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
2506 final int INCREMENT = 250;
2507 //currentCharacter is at position currentPosition-1
2508 if (this.checkNonExternalizedStringLiterals) {
2509 // reinitialize the current line for non externalize strings purpose
2513 if (currentCharacter == '\r') {
2514 int separatorPos = currentPosition - 6;
2515 if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2517 //System.out.println("CR-" + separatorPos);
2519 lineEnds[++linePtr] = separatorPos;
2520 } catch (IndexOutOfBoundsException e) {
2521 //linePtr value is correct
2522 int oldLength = lineEnds.length;
2523 int[] old = lineEnds;
2524 lineEnds = new int[oldLength + INCREMENT];
2525 System.arraycopy(old, 0, lineEnds, 0, oldLength);
2526 lineEnds[linePtr] = separatorPos;
2528 // look-ahead for merged cr+lf
2529 if (source[currentPosition] == '\n') {
2530 //System.out.println("look-ahead LF-" + currentPosition);
2531 lineEnds[linePtr] = currentPosition;
2539 if (currentCharacter == '\n') {
2540 //must merge eventual cr followed by lf
2541 if (wasAcr && (lineEnds[linePtr] == (currentPosition - 7))) {
2542 //System.out.println("merge LF-" + (currentPosition - 1));
2543 lineEnds[linePtr] = currentPosition - 6;
2545 int separatorPos = currentPosition - 6;
2546 if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
2548 // System.out.println("LF-" + separatorPos);
2550 lineEnds[++linePtr] = separatorPos;
2551 } catch (IndexOutOfBoundsException e) {
2552 //linePtr value is correct
2553 int oldLength = lineEnds.length;
2554 int[] old = lineEnds;
2555 lineEnds = new int[oldLength + INCREMENT];
2556 System.arraycopy(old, 0, lineEnds, 0, oldLength);
2557 lineEnds[linePtr] = separatorPos;
2564 public final void recordComment(boolean isJavadoc) {
2565 // a new annotation comment is recorded
2567 commentStops[++commentPtr] = isJavadoc
2570 } catch (IndexOutOfBoundsException e) {
2571 int oldStackLength = commentStops.length;
2572 int[] oldStack = commentStops;
2573 commentStops = new int[oldStackLength + 30];
2574 System.arraycopy(oldStack, 0, commentStops, 0, oldStackLength);
2575 commentStops[commentPtr] = isJavadoc ? currentPosition : -currentPosition;
2576 //grows the positions buffers too
2577 int[] old = commentStarts;
2578 commentStarts = new int[oldStackLength + 30];
2579 System.arraycopy(old, 0, commentStarts, 0, oldStackLength);
2581 //the buffer is of a correct size here
2582 commentStarts[commentPtr] = startPosition;
2584 public void resetTo(int begin, int end) {
2585 //reset the scanner to a given position where it may rescan again
2587 initialPosition = startPosition = currentPosition = begin;
2588 eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
2589 commentPtr = -1; // reset comment stack
2591 public final void scanSingleQuotedEscapeCharacter()
2592 throws InvalidInputException {
2593 // the string with "\\u" is a legal string of two chars \ and u
2594 //thus we use a direct access to the source (for regular cases).
2595 // if (unicodeAsBackSlash) {
2596 // // consume next character
2597 // unicodeAsBackSlash = false;
2598 // if (((currentCharacter = source[currentPosition++]) == '\\')
2599 // && (source[currentPosition] == 'u')) {
2600 // getNextUnicodeChar();
2602 // if (withoutUnicodePtr != 0) {
2603 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2607 currentCharacter = source[currentPosition++];
2608 switch (currentCharacter) {
2610 currentCharacter = '\'';
2613 currentCharacter = '\\';
2616 currentCharacter = '\\';
2620 public final void scanDoubleQuotedEscapeCharacter()
2621 throws InvalidInputException {
2622 // the string with "\\u" is a legal string of two chars \ and u
2623 //thus we use a direct access to the source (for regular cases).
2624 // if (unicodeAsBackSlash) {
2625 // // consume next character
2626 // unicodeAsBackSlash = false;
2627 // if (((currentCharacter = source[currentPosition++]) == '\\')
2628 // && (source[currentPosition] == 'u')) {
2629 // getNextUnicodeChar();
2631 // if (withoutUnicodePtr != 0) {
2632 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
2636 currentCharacter = source[currentPosition++];
2637 switch (currentCharacter) {
2639 // currentCharacter = '\b';
2642 currentCharacter = '\t';
2645 currentCharacter = '\n';
2648 // currentCharacter = '\f';
2651 currentCharacter = '\r';
2654 currentCharacter = '\"';
2657 currentCharacter = '\'';
2660 currentCharacter = '\\';
2663 currentCharacter = '$';
2666 // -----------octal escape--------------
2668 // OctalDigit OctalDigit
2669 // ZeroToThree OctalDigit OctalDigit
2670 int number = Character.getNumericValue(currentCharacter);
2671 if (number >= 0 && number <= 7) {
2672 boolean zeroToThreeNot = number > 3;
2673 if (Character.isDigit(currentCharacter = source[currentPosition++])) {
2674 int digit = Character.getNumericValue(currentCharacter);
2675 if (digit >= 0 && digit <= 7) {
2676 number = (number * 8) + digit;
2678 .isDigit(currentCharacter = source[currentPosition++])) {
2679 if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit
2680 // Digit --> ignore last character
2683 digit = Character.getNumericValue(currentCharacter);
2684 if (digit >= 0 && digit <= 7) {
2685 // has read \ZeroToThree OctalDigit OctalDigit
2686 number = (number * 8) + digit;
2687 } else { // has read \ZeroToThree OctalDigit NonOctalDigit
2688 // --> ignore last character
2692 } else { // has read \OctalDigit NonDigit--> ignore last
2696 } else { // has read \OctalDigit NonOctalDigit--> ignore last
2700 } else { // has read \OctalDigit --> ignore last character
2704 throw new InvalidInputException(INVALID_ESCAPE);
2705 currentCharacter = (char) number;
2708 // throw new InvalidInputException(INVALID_ESCAPE);
2711 // public int scanIdentifierOrKeyword() throws InvalidInputException {
2712 // return scanIdentifierOrKeyword( false );
2714 public int scanIdentifierOrKeyword(boolean isVariable)
2715 throws InvalidInputException {
2717 //first dispatch on the first char.
2718 //then the length. If there are several
2719 //keywors with the same length AND the same first char, then do another
2720 //disptach on the second char :-)...cool....but fast !
2721 useAssertAsAnIndentifier = false;
2722 while (getNextCharAsJavaIdentifierPart()) {
2725 // if (new String(getCurrentTokenSource()).equals("$this")) {
2726 // return TokenNamethis;
2728 return TokenNameVariable;
2733 // if (withoutUnicodePtr == 0)
2734 //quick test on length == 1 but not on length > 12 while most identifier
2735 //have a length which is <= 12...but there are lots of identifier with
2738 if ((length = currentPosition - startPosition) == 1)
2739 return TokenNameIdentifier;
2741 data = new char[length];
2742 index = startPosition;
2743 for (int i = 0; i < length; i++) {
2744 data[i] = Character.toLowerCase(source[index + i]);
2748 // if ((length = withoutUnicodePtr) == 1)
2749 // return TokenNameIdentifier;
2750 // // data = withoutUnicodeBuffer;
2751 // data = new char[withoutUnicodeBuffer.length];
2752 // for (int i = 0; i < withoutUnicodeBuffer.length; i++) {
2753 // data[i] = Character.toLowerCase(withoutUnicodeBuffer[i]);
2757 firstLetter = data[index];
2758 switch (firstLetter) {
2763 if ((data[++index] == '_') && (data[++index] == 'f')
2764 && (data[++index] == 'i') && (data[++index] == 'l')
2765 && (data[++index] == 'e') && (data[++index] == '_')
2766 && (data[++index] == '_'))
2767 return TokenNameFILE;
2768 index = 0; //__LINE__
2769 if ((data[++index] == '_') && (data[++index] == 'l')
2770 && (data[++index] == 'i') && (data[++index] == 'n')
2771 && (data[++index] == 'e') && (data[++index] == '_')
2772 && (data[++index] == '_'))
2773 return TokenNameLINE;
2777 if ((data[++index] == '_') && (data[++index] == 'c')
2778 && (data[++index] == 'l') && (data[++index] == 'a')
2779 && (data[++index] == 's') && (data[++index] == 's')
2780 && (data[++index] == '_') && (data[++index] == '_'))
2781 return TokenNameCLASS_C;
2785 if ((data[++index] == '_') && (data[++index] == 'm')
2786 && (data[++index] == 'e') && (data[++index] == 't')
2787 && (data[++index] == 'h') && (data[++index] == 'o')
2788 && (data[++index] == 'd') && (data[++index] == '_')
2789 && (data[++index] == '_'))
2790 return TokenNameMETHOD_C;
2794 if ((data[++index] == '_') && (data[++index] == 'f')
2795 && (data[++index] == 'u') && (data[++index] == 'n')
2796 && (data[++index] == 'c') && (data[++index] == 't')
2797 && (data[++index] == 'i') && (data[++index] == 'o')
2798 && (data[++index] == 'n') && (data[++index] == '_')
2799 && (data[++index] == '_'))
2800 return TokenNameFUNC_C;
2803 return TokenNameIdentifier;
2805 // as and array abstract
2809 if ((data[++index] == 's')) {
2812 return TokenNameIdentifier;
2816 if ((data[++index] == 'n') && (data[++index] == 'd')) {
2817 return TokenNameand;
2819 return TokenNameIdentifier;
2823 if ((data[++index] == 'r') && (data[++index] == 'r')
2824 && (data[++index] == 'a') && (data[++index] == 'y'))
2825 return TokenNamearray;
2827 return TokenNameIdentifier;
2829 if ((data[++index] == 'b') && (data[++index] == 's')
2830 && (data[++index] == 't') && (data[++index] == 'r')
2831 && (data[++index] == 'a') && (data[++index] == 'c')
2832 && (data[++index] == 't'))
2833 return TokenNameabstract;
2835 return TokenNameIdentifier;
2837 return TokenNameIdentifier;
2843 if ((data[++index] == 'r') && (data[++index] == 'e')
2844 && (data[++index] == 'a') && (data[++index] == 'k'))
2845 return TokenNamebreak;
2847 return TokenNameIdentifier;
2849 return TokenNameIdentifier;
2852 //case catch class clone const continue
2855 if ((data[++index] == 'a') && (data[++index] == 's')
2856 && (data[++index] == 'e'))
2857 return TokenNamecase;
2859 return TokenNameIdentifier;
2861 if ((data[++index] == 'a') && (data[++index] == 't')
2862 && (data[++index] == 'c') && (data[++index] == 'h'))
2863 return TokenNamecatch;
2865 if ((data[++index] == 'l') && (data[++index] == 'a')
2866 && (data[++index] == 's') && (data[++index] == 's'))
2867 return TokenNameclass;
2869 if ((data[++index] == 'l') && (data[++index] == 'o')
2870 && (data[++index] == 'n') && (data[++index] == 'e'))
2871 return TokenNameclone;
2873 if ((data[++index] == 'o') && (data[++index] == 'n')
2874 && (data[++index] == 's') && (data[++index] == 't'))
2875 return TokenNameconst;
2877 return TokenNameIdentifier;
2879 if ((data[++index] == 'o') && (data[++index] == 'n')
2880 && (data[++index] == 't') && (data[++index] == 'i')
2881 && (data[++index] == 'n') && (data[++index] == 'u')
2882 && (data[++index] == 'e'))
2883 return TokenNamecontinue;
2885 return TokenNameIdentifier;
2887 return TokenNameIdentifier;
2890 // declare default do die
2891 // TODO delete define ==> no keyword !
2894 if ((data[++index] == 'o'))
2897 return TokenNameIdentifier;
2899 // if ((data[++index] == 'e')
2900 // && (data[++index] == 'f')
2901 // && (data[++index] == 'i')
2902 // && (data[++index] == 'n')
2903 // && (data[++index] == 'e'))
2904 // return TokenNamedefine;
2906 // return TokenNameIdentifier;
2908 if ((data[++index] == 'e') && (data[++index] == 'c')
2909 && (data[++index] == 'l') && (data[++index] == 'a')
2910 && (data[++index] == 'r') && (data[++index] == 'e'))
2911 return TokenNamedeclare;
2913 if ((data[++index] == 'e') && (data[++index] == 'f')
2914 && (data[++index] == 'a') && (data[++index] == 'u')
2915 && (data[++index] == 'l') && (data[++index] == 't'))
2916 return TokenNamedefault;
2918 return TokenNameIdentifier;
2920 return TokenNameIdentifier;
2923 //echo else exit elseif extends eval
2926 if ((data[++index] == 'c') && (data[++index] == 'h')
2927 && (data[++index] == 'o'))
2928 return TokenNameecho;
2929 else if ((data[index] == 'l') && (data[++index] == 's')
2930 && (data[++index] == 'e'))
2931 return TokenNameelse;
2932 else if ((data[index] == 'x') && (data[++index] == 'i')
2933 && (data[++index] == 't'))
2934 return TokenNameexit;
2935 else if ((data[index] == 'v') && (data[++index] == 'a')
2936 && (data[++index] == 'l'))
2937 return TokenNameeval;
2939 return TokenNameIdentifier;
2942 if ((data[++index] == 'n') && (data[++index] == 'd')
2943 && (data[++index] == 'i') && (data[++index] == 'f'))
2944 return TokenNameendif;
2945 if ((data[index] == 'm') && (data[++index] == 'p')
2946 && (data[++index] == 't') && (data[++index] == 'y'))
2947 return TokenNameempty;
2949 return TokenNameIdentifier;
2952 if ((data[++index] == 'n') && (data[++index] == 'd')
2953 && (data[++index] == 'f') && (data[++index] == 'o')
2954 && (data[++index] == 'r'))
2955 return TokenNameendfor;
2956 else if ((data[index] == 'l') && (data[++index] == 's')
2957 && (data[++index] == 'e') && (data[++index] == 'i')
2958 && (data[++index] == 'f'))
2959 return TokenNameelseif;
2961 return TokenNameIdentifier;
2963 if ((data[++index] == 'x') && (data[++index] == 't')
2964 && (data[++index] == 'e') && (data[++index] == 'n')
2965 && (data[++index] == 'd') && (data[++index] == 's'))
2966 return TokenNameextends;
2968 return TokenNameIdentifier;
2971 if ((data[++index] == 'n') && (data[++index] == 'd')
2972 && (data[++index] == 'w') && (data[++index] == 'h')
2973 && (data[++index] == 'i') && (data[++index] == 'l')
2974 && (data[++index] == 'e'))
2975 return TokenNameendwhile;
2977 return TokenNameIdentifier;
2980 if ((data[++index] == 'n') && (data[++index] == 'd')
2981 && (data[++index] == 's') && (data[++index] == 'w')
2982 && (data[++index] == 'i') && (data[++index] == 't')
2983 && (data[++index] == 'c') && (data[++index] == 'h'))
2984 return TokenNameendswitch;
2986 return TokenNameIdentifier;
2989 if ((data[++index] == 'n') && (data[++index] == 'd')
2990 && (data[++index] == 'd') && (data[++index] == 'e')
2991 && (data[++index] == 'c') && (data[++index] == 'l')
2992 && (data[++index] == 'a') && (data[++index] == 'r')
2993 && (data[++index] == 'e'))
2994 return TokenNameendforeach;
2996 if ((data[++index] == 'n') // endforeach
2997 && (data[++index] == 'd') && (data[++index] == 'f')
2998 && (data[++index] == 'o') && (data[++index] == 'r')
2999 && (data[++index] == 'e') && (data[++index] == 'a')
3000 && (data[++index] == 'c') && (data[++index] == 'h'))
3001 return TokenNameendforeach;
3003 return TokenNameIdentifier;
3005 return TokenNameIdentifier;
3008 //for false final function
3011 if ((data[++index] == 'o') && (data[++index] == 'r'))
3012 return TokenNamefor;
3014 return TokenNameIdentifier;
3016 // if ((data[++index] == 'a') && (data[++index] == 'l')
3017 // && (data[++index] == 's') && (data[++index] == 'e'))
3018 // return TokenNamefalse;
3019 if ((data[++index] == 'i') && (data[++index] == 'n')
3020 && (data[++index] == 'a') && (data[++index] == 'l'))
3021 return TokenNamefinal;
3023 return TokenNameIdentifier;
3026 if ((data[++index] == 'o') && (data[++index] == 'r')
3027 && (data[++index] == 'e') && (data[++index] == 'a')
3028 && (data[++index] == 'c') && (data[++index] == 'h'))
3029 return TokenNameforeach;
3031 return TokenNameIdentifier;
3034 if ((data[++index] == 'u') && (data[++index] == 'n')
3035 && (data[++index] == 'c') && (data[++index] == 't')
3036 && (data[++index] == 'i') && (data[++index] == 'o')
3037 && (data[++index] == 'n'))
3038 return TokenNamefunction;
3040 return TokenNameIdentifier;
3042 return TokenNameIdentifier;
3047 if ((data[++index] == 'l') && (data[++index] == 'o')
3048 && (data[++index] == 'b') && (data[++index] == 'a')
3049 && (data[++index] == 'l')) {
3050 return TokenNameglobal;
3053 return TokenNameIdentifier;
3055 //if int isset include include_once instanceof interface implements
3058 if (data[++index] == 'f')
3061 return TokenNameIdentifier;
3063 // if ((data[++index] == 'n') && (data[++index] == 't'))
3064 // return TokenNameint;
3066 // return TokenNameIdentifier;
3068 if ((data[++index] == 's') && (data[++index] == 's')
3069 && (data[++index] == 'e') && (data[++index] == 't'))
3070 return TokenNameisset;
3072 return TokenNameIdentifier;
3074 if ((data[++index] == 'n') && (data[++index] == 'c')
3075 && (data[++index] == 'l') && (data[++index] == 'u')
3076 && (data[++index] == 'd') && (data[++index] == 'e'))
3077 return TokenNameinclude;
3079 return TokenNameIdentifier;
3082 if ((data[++index] == 'n') && (data[++index] == 't')
3083 && (data[++index] == 'e') && (data[++index] == 'r')
3084 && (data[++index] == 'f') && (data[++index] == 'a')
3085 && (data[++index] == 'c') && (data[++index] == 'e'))
3086 return TokenNameinterface;
3088 return TokenNameIdentifier;
3091 if ((data[++index] == 'n') && (data[++index] == 's')
3092 && (data[++index] == 't') && (data[++index] == 'a')
3093 && (data[++index] == 'n') && (data[++index] == 'c')
3094 && (data[++index] == 'e') && (data[++index] == 'o')
3095 && (data[++index] == 'f'))
3096 return TokenNameinstanceof;
3097 if ((data[index] == 'm') && (data[++index] == 'p')
3098 && (data[++index] == 'l') && (data[++index] == 'e')
3099 && (data[++index] == 'm') && (data[++index] == 'e')
3100 && (data[++index] == 'n') && (data[++index] == 't')
3101 && (data[++index] == 's'))
3102 return TokenNameimplements;
3104 return TokenNameIdentifier;
3106 if ((data[++index] == 'n') && (data[++index] == 'c')
3107 && (data[++index] == 'l') && (data[++index] == 'u')
3108 && (data[++index] == 'd') && (data[++index] == 'e')
3109 && (data[++index] == '_') && (data[++index] == 'o')
3110 && (data[++index] == 'n') && (data[++index] == 'c')
3111 && (data[++index] == 'e'))
3112 return TokenNameinclude_once;
3114 return TokenNameIdentifier;
3116 return TokenNameIdentifier;
3121 if ((data[++index] == 'i') && (data[++index] == 's')
3122 && (data[++index] == 't')) {
3123 return TokenNamelist;
3126 return TokenNameIdentifier;
3131 if ((data[++index] == 'e') && (data[++index] == 'w'))
3132 return TokenNamenew;
3134 return TokenNameIdentifier;
3136 // if ((data[++index] == 'u') && (data[++index] == 'l')
3137 // && (data[++index] == 'l'))
3138 // return TokenNamenull;
3140 // return TokenNameIdentifier;
3142 return TokenNameIdentifier;
3147 if (data[++index] == 'r') {
3151 // if (length == 12) {
3152 // if ((data[++index] == 'l')
3153 // && (data[++index] == 'd')
3154 // && (data[++index] == '_')
3155 // && (data[++index] == 'f')
3156 // && (data[++index] == 'u')
3157 // && (data[++index] == 'n')
3158 // && (data[++index] == 'c')
3159 // && (data[++index] == 't')
3160 // && (data[++index] == 'i')
3161 // && (data[++index] == 'o')
3162 // && (data[++index] == 'n')) {
3163 // return TokenNameold_function;
3166 return TokenNameIdentifier;
3168 // print public private protected
3171 if ((data[++index] == 'r') && (data[++index] == 'i')
3172 && (data[++index] == 'n') && (data[++index] == 't')) {
3173 return TokenNameprint;
3175 return TokenNameIdentifier;
3177 if ((data[++index] == 'u') && (data[++index] == 'b')
3178 && (data[++index] == 'l') && (data[++index] == 'i')
3179 && (data[++index] == 'c')) {
3180 return TokenNamepublic;
3182 return TokenNameIdentifier;
3184 if ((data[++index] == 'r') && (data[++index] == 'i')
3185 && (data[++index] == 'v') && (data[++index] == 'a')
3186 && (data[++index] == 't') && (data[++index] == 'e')) {
3187 return TokenNameprivate;
3189 return TokenNameIdentifier;
3191 if ((data[++index] == 'r') && (data[++index] == 'o')
3192 && (data[++index] == 't') && (data[++index] == 'e')
3193 && (data[++index] == 'c') && (data[++index] == 't')
3194 && (data[++index] == 'e') && (data[++index] == 'd')) {
3195 return TokenNameprotected;
3197 return TokenNameIdentifier;
3199 return TokenNameIdentifier;
3201 //return require require_once
3203 if ((data[++index] == 'e') && (data[++index] == 't')
3204 && (data[++index] == 'u') && (data[++index] == 'r')
3205 && (data[++index] == 'n')) {
3206 return TokenNamereturn;
3208 } else if (length == 7) {
3209 if ((data[++index] == 'e') && (data[++index] == 'q')
3210 && (data[++index] == 'u') && (data[++index] == 'i')
3211 && (data[++index] == 'r') && (data[++index] == 'e')) {
3212 return TokenNamerequire;
3214 } else if (length == 12) {
3215 if ((data[++index] == 'e') && (data[++index] == 'q')
3216 && (data[++index] == 'u') && (data[++index] == 'i')
3217 && (data[++index] == 'r') && (data[++index] == 'e')
3218 && (data[++index] == '_') && (data[++index] == 'o')
3219 && (data[++index] == 'n') && (data[++index] == 'c')
3220 && (data[++index] == 'e')) {
3221 return TokenNamerequire_once;
3224 return TokenNameIdentifier;
3229 if (data[++index] == 't')
3230 if ((data[++index] == 'a') && (data[++index] == 't')
3231 && (data[++index] == 'i') && (data[++index] == 'c')) {
3232 return TokenNamestatic;
3234 return TokenNameIdentifier;
3235 else if ((data[index] == 'w') && (data[++index] == 'i')
3236 && (data[++index] == 't') && (data[++index] == 'c')
3237 && (data[++index] == 'h'))
3238 return TokenNameswitch;
3240 return TokenNameIdentifier;
3242 return TokenNameIdentifier;
3248 if ((data[++index] == 'r') && (data[++index] == 'y'))
3249 return TokenNametry;
3251 return TokenNameIdentifier;
3253 // if ((data[++index] == 'r') && (data[++index] == 'u')
3254 // && (data[++index] == 'e'))
3255 // return TokenNametrue;
3257 // return TokenNameIdentifier;
3259 if ((data[++index] == 'h') && (data[++index] == 'r')
3260 && (data[++index] == 'o') && (data[++index] == 'w'))
3261 return TokenNamethrow;
3263 return TokenNameIdentifier;
3265 return TokenNameIdentifier;
3271 if ((data[++index] == 's') && (data[++index] == 'e'))
3272 return TokenNameuse;
3274 return TokenNameIdentifier;
3276 if ((data[++index] == 'n') && (data[++index] == 's')
3277 && (data[++index] == 'e') && (data[++index] == 't'))
3278 return TokenNameunset;
3280 return TokenNameIdentifier;
3282 return TokenNameIdentifier;
3288 if ((data[++index] == 'a') && (data[++index] == 'r'))
3289 return TokenNamevar;
3291 return TokenNameIdentifier;
3293 return TokenNameIdentifier;
3299 if ((data[++index] == 'h') && (data[++index] == 'i')
3300 && (data[++index] == 'l') && (data[++index] == 'e'))
3301 return TokenNamewhile;
3303 return TokenNameIdentifier;
3304 //case 6:if ( (data[++index] =='i') && (data[++index]=='d') &&
3305 // (data[++index]=='e') && (data[++index]=='f')&&
3306 // (data[++index]=='p'))
3307 //return TokenNamewidefp ;
3309 //return TokenNameIdentifier;
3311 return TokenNameIdentifier;
3317 if ((data[++index] == 'o') && (data[++index] == 'r'))
3318 return TokenNamexor;
3320 return TokenNameIdentifier;
3322 return TokenNameIdentifier;
3325 return TokenNameIdentifier;
3328 public int scanNumber(boolean dotPrefix) throws InvalidInputException {
3329 //when entering this method the currentCharacter is the firt
3330 //digit of the number , i.e. it may be preceeded by a . when
3332 boolean floating = dotPrefix;
3333 if ((!dotPrefix) && (currentCharacter == '0')) {
3334 if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
3335 //force the first char of the hexa number do exist...
3336 // consume next character
3337 unicodeAsBackSlash = false;
3338 currentCharacter = source[currentPosition++];
3339 // if (((currentCharacter = source[currentPosition++]) == '\\')
3340 // && (source[currentPosition] == 'u')) {
3341 // getNextUnicodeChar();
3343 // if (withoutUnicodePtr != 0) {
3344 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3347 if (Character.digit(currentCharacter, 16) == -1)
3348 throw new InvalidInputException(INVALID_HEXA);
3350 while (getNextCharAsDigit(16)) {
3352 // if (getNextChar('l', 'L') >= 0)
3353 // return TokenNameLongLiteral;
3355 return TokenNameIntegerLiteral;
3357 //there is x or X in the number
3358 //potential octal ! ... some one may write 000099.0 ! thus 00100 <
3359 // 00078.0 is true !!!!! crazy language
3360 if (getNextCharAsDigit()) {
3361 //-------------potential octal-----------------
3362 while (getNextCharAsDigit()) {
3364 // if (getNextChar('l', 'L') >= 0) {
3365 // return TokenNameLongLiteral;
3368 // if (getNextChar('f', 'F') >= 0) {
3369 // return TokenNameFloatingPointLiteral;
3371 if (getNextChar('d', 'D') >= 0) {
3372 return TokenNameDoubleLiteral;
3373 } else { //make the distinction between octal and float ....
3374 if (getNextChar('.')) { //bingo ! ....
3375 while (getNextCharAsDigit()) {
3377 if (getNextChar('e', 'E') >= 0) {
3378 // consume next character
3379 unicodeAsBackSlash = false;
3380 currentCharacter = source[currentPosition++];
3381 // if (((currentCharacter = source[currentPosition++]) == '\\')
3382 // && (source[currentPosition] == 'u')) {
3383 // getNextUnicodeChar();
3385 // if (withoutUnicodePtr != 0) {
3386 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3389 if ((currentCharacter == '-') || (currentCharacter == '+')) {
3390 // consume next character
3391 unicodeAsBackSlash = false;
3392 currentCharacter = source[currentPosition++];
3393 // if (((currentCharacter = source[currentPosition++]) == '\\')
3394 // && (source[currentPosition] == 'u')) {
3395 // getNextUnicodeChar();
3397 // if (withoutUnicodePtr != 0) {
3398 // withoutUnicodeBuffer[++withoutUnicodePtr] =
3399 // currentCharacter;
3403 if (!Character.isDigit(currentCharacter))
3404 throw new InvalidInputException(INVALID_FLOAT);
3405 while (getNextCharAsDigit()) {
3408 // if (getNextChar('f', 'F') >= 0)
3409 // return TokenNameFloatingPointLiteral;
3410 getNextChar('d', 'D'); //jump over potential d or D
3411 return TokenNameDoubleLiteral;
3413 return TokenNameIntegerLiteral;
3420 while (getNextCharAsDigit()) {
3422 // if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
3423 // return TokenNameLongLiteral;
3424 if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
3425 while (getNextCharAsDigit()) {
3429 //if floating is true both exponant and suffix may be optional
3430 if (getNextChar('e', 'E') >= 0) {
3432 // consume next character
3433 unicodeAsBackSlash = false;
3434 currentCharacter = source[currentPosition++];
3435 // if (((currentCharacter = source[currentPosition++]) == '\\')
3436 // && (source[currentPosition] == 'u')) {
3437 // getNextUnicodeChar();
3439 // if (withoutUnicodePtr != 0) {
3440 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3443 if ((currentCharacter == '-') || (currentCharacter == '+')) { // consume
3446 unicodeAsBackSlash = false;
3447 currentCharacter = source[currentPosition++];
3448 // if (((currentCharacter = source[currentPosition++]) == '\\')
3449 // && (source[currentPosition] == 'u')) {
3450 // getNextUnicodeChar();
3452 // if (withoutUnicodePtr != 0) {
3453 // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3457 if (!Character.isDigit(currentCharacter))
3458 throw new InvalidInputException(INVALID_FLOAT);
3459 while (getNextCharAsDigit()) {
3462 if (getNextChar('d', 'D') >= 0)
3463 return TokenNameDoubleLiteral;
3464 // if (getNextChar('f', 'F') >= 0)
3465 // return TokenNameFloatingPointLiteral;
3466 //the long flag has been tested before
3467 return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
3470 * Search the line number corresponding to a specific position
3473 public final int getLineNumber(int position) {
3474 if (lineEnds == null)
3476 int length = linePtr + 1;
3479 int g = 0, d = length - 1;
3483 if (position < lineEnds[m]) {
3485 } else if (position > lineEnds[m]) {
3491 if (position < lineEnds[m]) {
3496 public void setPHPMode(boolean mode) {
3499 public final void setSource(char[] source) {
3500 //the source-buffer is set to sourceString
3501 if (source == null) {
3502 this.source = new char[0];
3504 this.source = source;
3507 initialPosition = currentPosition = 0;
3508 containsAssertKeyword = false;
3509 withoutUnicodeBuffer = new char[this.source.length];
3510 encapsedStringStack = new Stack();
3512 public String toString() {
3513 if (startPosition == source.length)
3514 return "EOF\n\n" + new String(source); //$NON-NLS-1$
3515 if (currentPosition > source.length)
3516 return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
3517 char front[] = new char[startPosition];
3518 System.arraycopy(source, 0, front, 0, startPosition);
3519 int middleLength = (currentPosition - 1) - startPosition + 1;
3521 if (middleLength > -1) {
3522 middle = new char[middleLength];
3523 System.arraycopy(source, startPosition, middle, 0, middleLength);
3525 middle = new char[0];
3527 char end[] = new char[source.length - (currentPosition - 1)];
3528 System.arraycopy(source, (currentPosition - 1) + 1, end, 0, source.length
3529 - (currentPosition - 1) - 1);
3530 return new String(front)
3531 + "\n===============================\nStarts here -->" //$NON-NLS-1$
3532 + new String(middle)
3533 + "<-- Ends here\n===============================\n" //$NON-NLS-1$
3536 public final String toStringAction(int act) {
3538 case TokenNameERROR :
3539 return "ScannerError"; // + new String(getCurrentTokenSource()) + ")";
3541 case TokenNameINLINE_HTML :
3542 return "Inline-HTML(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3543 case TokenNameIdentifier :
3544 return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3545 case TokenNameVariable :
3546 return "Variable(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3547 case TokenNameabstract :
3548 return "abstract"; //$NON-NLS-1$
3550 return "AND"; //$NON-NLS-1$
3551 case TokenNamearray :
3552 return "array"; //$NON-NLS-1$
3554 return "as"; //$NON-NLS-1$
3555 case TokenNamebreak :
3556 return "break"; //$NON-NLS-1$
3557 case TokenNamecase :
3558 return "case"; //$NON-NLS-1$
3559 case TokenNameclass :
3560 return "class"; //$NON-NLS-1$
3561 case TokenNamecatch :
3562 return "catch"; //$NON-NLS-1$
3563 case TokenNameclone :
3566 case TokenNameconst :
3569 case TokenNamecontinue :
3570 return "continue"; //$NON-NLS-1$
3571 case TokenNamedefault :
3572 return "default"; //$NON-NLS-1$
3573 // case TokenNamedefine :
3574 // return "define"; //$NON-NLS-1$
3576 return "do"; //$NON-NLS-1$
3577 case TokenNameecho :
3578 return "echo"; //$NON-NLS-1$
3579 case TokenNameelse :
3580 return "else"; //$NON-NLS-1$
3581 case TokenNameelseif :
3582 return "elseif"; //$NON-NLS-1$
3583 case TokenNameendfor :
3584 return "endfor"; //$NON-NLS-1$
3585 case TokenNameendforeach :
3586 return "endforeach"; //$NON-NLS-1$
3587 case TokenNameendif :
3588 return "endif"; //$NON-NLS-1$
3589 case TokenNameendswitch :
3590 return "endswitch"; //$NON-NLS-1$
3591 case TokenNameendwhile :
3592 return "endwhile"; //$NON-NLS-1$
3593 case TokenNameextends :
3594 return "extends"; //$NON-NLS-1$
3595 // case TokenNamefalse :
3596 // return "false"; //$NON-NLS-1$
3597 case TokenNamefinal :
3598 return "final"; //$NON-NLS-1$
3600 return "for"; //$NON-NLS-1$
3601 case TokenNameforeach :
3602 return "foreach"; //$NON-NLS-1$
3603 case TokenNamefunction :
3604 return "function"; //$NON-NLS-1$
3605 case TokenNameglobal :
3606 return "global"; //$NON-NLS-1$
3608 return "if"; //$NON-NLS-1$
3609 case TokenNameimplements :
3610 return "implements"; //$NON-NLS-1$
3611 case TokenNameinclude :
3612 return "include"; //$NON-NLS-1$
3613 case TokenNameinclude_once :
3614 return "include_once"; //$NON-NLS-1$
3615 case TokenNameinstanceof :
3616 return "instanceof"; //$NON-NLS-1$
3617 case TokenNameinterface :
3618 return "interface"; //$NON-NLS-1$
3619 case TokenNameisset :
3620 return "isset"; //$NON-NLS-1$
3621 case TokenNamelist :
3622 return "list"; //$NON-NLS-1$
3624 return "new"; //$NON-NLS-1$
3625 // case TokenNamenull :
3626 // return "null"; //$NON-NLS-1$
3628 return "OR"; //$NON-NLS-1$
3629 case TokenNameprint :
3630 return "print"; //$NON-NLS-1$
3631 case TokenNameprivate :
3632 return "private"; //$NON-NLS-1$
3633 case TokenNameprotected :
3634 return "protected"; //$NON-NLS-1$
3635 case TokenNamepublic :
3636 return "public"; //$NON-NLS-1$
3637 case TokenNamerequire :
3638 return "require"; //$NON-NLS-1$
3639 case TokenNamerequire_once :
3640 return "require_once"; //$NON-NLS-1$
3641 case TokenNamereturn :
3642 return "return"; //$NON-NLS-1$
3643 case TokenNamestatic :
3644 return "static"; //$NON-NLS-1$
3645 case TokenNameswitch :
3646 return "switch"; //$NON-NLS-1$
3647 // case TokenNametrue :
3648 // return "true"; //$NON-NLS-1$
3649 case TokenNameunset :
3650 return "unset"; //$NON-NLS-1$
3652 return "var"; //$NON-NLS-1$
3653 case TokenNamewhile :
3654 return "while"; //$NON-NLS-1$
3656 return "XOR"; //$NON-NLS-1$
3657 // case TokenNamethis :
3658 // return "$this"; //$NON-NLS-1$
3659 case TokenNameIntegerLiteral :
3660 return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3661 case TokenNameDoubleLiteral :
3662 return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3663 case TokenNameStringLiteral :
3664 return "StringLiteral(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3665 case TokenNameStringConstant :
3666 return "StringConstant(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3667 case TokenNameStringInterpolated :
3668 return "StringInterpolated(" + new String(getCurrentTokenSource())
3669 + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3670 case TokenNameEncapsedString0 :
3671 return "`"; //$NON-NLS-1$
3672 case TokenNameEncapsedString1 :
3673 return "\'"; //$NON-NLS-1$
3674 case TokenNameEncapsedString2 :
3675 return "\""; //$NON-NLS-1$
3676 case TokenNameSTRING :
3677 return "STRING(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
3678 case TokenNameHEREDOC :
3679 return "HEREDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3680 case TokenNamePLUS_PLUS :
3681 return "++"; //$NON-NLS-1$
3682 case TokenNameMINUS_MINUS :
3683 return "--"; //$NON-NLS-1$
3684 case TokenNameEQUAL_EQUAL :
3685 return "=="; //$NON-NLS-1$
3686 case TokenNameEQUAL_EQUAL_EQUAL :
3687 return "==="; //$NON-NLS-1$
3688 case TokenNameEQUAL_GREATER :
3689 return "=>"; //$NON-NLS-1$
3690 case TokenNameLESS_EQUAL :
3691 return "<="; //$NON-NLS-1$
3692 case TokenNameGREATER_EQUAL :
3693 return ">="; //$NON-NLS-1$
3694 case TokenNameNOT_EQUAL :
3695 return "!="; //$NON-NLS-1$
3696 case TokenNameNOT_EQUAL_EQUAL :
3697 return "!=="; //$NON-NLS-1$
3698 case TokenNameLEFT_SHIFT :
3699 return "<<"; //$NON-NLS-1$
3700 case TokenNameRIGHT_SHIFT :
3701 return ">>"; //$NON-NLS-1$
3702 case TokenNamePLUS_EQUAL :
3703 return "+="; //$NON-NLS-1$
3704 case TokenNameMINUS_EQUAL :
3705 return "-="; //$NON-NLS-1$
3706 case TokenNameMULTIPLY_EQUAL :
3707 return "*="; //$NON-NLS-1$
3708 case TokenNameDIVIDE_EQUAL :
3709 return "/="; //$NON-NLS-1$
3710 case TokenNameAND_EQUAL :
3711 return "&="; //$NON-NLS-1$
3712 case TokenNameOR_EQUAL :
3713 return "|="; //$NON-NLS-1$
3714 case TokenNameXOR_EQUAL :
3715 return "^="; //$NON-NLS-1$
3716 case TokenNameREMAINDER_EQUAL :
3717 return "%="; //$NON-NLS-1$
3718 case TokenNameDOT_EQUAL :
3719 return ".="; //$NON-NLS-1$
3720 case TokenNameLEFT_SHIFT_EQUAL :
3721 return "<<="; //$NON-NLS-1$
3722 case TokenNameRIGHT_SHIFT_EQUAL :
3723 return ">>="; //$NON-NLS-1$
3724 case TokenNameOR_OR :
3725 return "||"; //$NON-NLS-1$
3726 case TokenNameAND_AND :
3727 return "&&"; //$NON-NLS-1$
3728 case TokenNamePLUS :
3729 return "+"; //$NON-NLS-1$
3730 case TokenNameMINUS :
3731 return "-"; //$NON-NLS-1$
3732 case TokenNameMINUS_GREATER :
3735 return "!"; //$NON-NLS-1$
3736 case TokenNameREMAINDER :
3737 return "%"; //$NON-NLS-1$
3739 return "^"; //$NON-NLS-1$
3741 return "&"; //$NON-NLS-1$
3742 case TokenNameMULTIPLY :
3743 return "*"; //$NON-NLS-1$
3745 return "|"; //$NON-NLS-1$
3746 case TokenNameTWIDDLE :
3747 return "~"; //$NON-NLS-1$
3748 case TokenNameTWIDDLE_EQUAL :
3749 return "~="; //$NON-NLS-1$
3750 case TokenNameDIVIDE :
3751 return "/"; //$NON-NLS-1$
3752 case TokenNameGREATER :
3753 return ">"; //$NON-NLS-1$
3754 case TokenNameLESS :
3755 return "<"; //$NON-NLS-1$
3756 case TokenNameLPAREN :
3757 return "("; //$NON-NLS-1$
3758 case TokenNameRPAREN :
3759 return ")"; //$NON-NLS-1$
3760 case TokenNameLBRACE :
3761 return "{"; //$NON-NLS-1$
3762 case TokenNameRBRACE :
3763 return "}"; //$NON-NLS-1$
3764 case TokenNameLBRACKET :
3765 return "["; //$NON-NLS-1$
3766 case TokenNameRBRACKET :
3767 return "]"; //$NON-NLS-1$
3768 case TokenNameSEMICOLON :
3769 return ";"; //$NON-NLS-1$
3770 case TokenNameQUESTION :
3771 return "?"; //$NON-NLS-1$
3772 case TokenNameCOLON :
3773 return ":"; //$NON-NLS-1$
3774 case TokenNameCOMMA :
3775 return ","; //$NON-NLS-1$
3777 return "."; //$NON-NLS-1$
3778 case TokenNameEQUAL :
3779 return "="; //$NON-NLS-1$
3782 case TokenNameDOLLAR :
3784 case TokenNameDOLLAR_LBRACE :
3787 return "EOF"; //$NON-NLS-1$
3788 case TokenNameWHITESPACE :
3789 return "WHITESPACE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3790 case TokenNameCOMMENT_LINE :
3791 return "COMMENT_LINE(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3792 case TokenNameCOMMENT_BLOCK :
3793 return "COMMENT_BLOCK(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3794 case TokenNameCOMMENT_PHPDOC :
3795 return "COMMENT_PHPDOC(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
3796 // case TokenNameHTML :
3797 // return "HTML(" + new String(getCurrentTokenSource()) + ")";
3799 case TokenNameFILE :
3800 return "__FILE__"; //$NON-NLS-1$
3801 case TokenNameLINE :
3802 return "__LINE__"; //$NON-NLS-1$
3803 case TokenNameCLASS_C :
3804 return "__CLASS__"; //$NON-NLS-1$
3805 case TokenNameMETHOD_C :
3806 return "__METHOD__"; //$NON-NLS-1$
3807 case TokenNameFUNC_C :
3808 return "__FUNCTION__"; //$NON-NLS-1
3809 case TokenNameboolCAST :
3810 return "( bool )"; //$NON-NLS-1$
3811 case TokenNameintCAST :
3812 return "( int )"; //$NON-NLS-1$
3813 case TokenNamedoubleCAST :
3814 return "( double )"; //$NON-NLS-1$
3815 case TokenNameobjectCAST :
3816 return "( object )"; //$NON-NLS-1$
3817 case TokenNamestringCAST :
3818 return "( string )"; //$NON-NLS-1$
3820 return "not-a-token(" + (new Integer(act)) + ") "
3821 + new String(getCurrentTokenSource()); //$NON-NLS-1$
3824 public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
3825 boolean checkNonExternalizedStringLiterals) {
3826 this(tokenizeComments, tokenizeWhiteSpace,
3827 checkNonExternalizedStringLiterals, false);
3829 public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
3830 boolean checkNonExternalizedStringLiterals, boolean assertMode) {
3831 this(tokenizeComments, tokenizeWhiteSpace,
3832 checkNonExternalizedStringLiterals, assertMode, false);
3834 public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
3835 boolean checkNonExternalizedStringLiterals, boolean assertMode,
3836 boolean tokenizeStrings) {
3837 this.eofPosition = Integer.MAX_VALUE;
3838 this.tokenizeComments = tokenizeComments;
3839 this.tokenizeWhiteSpace = tokenizeWhiteSpace;
3840 this.tokenizeStrings = tokenizeStrings;
3841 this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
3842 this.assertMode = assertMode;
3843 this.encapsedStringStack = null;
3845 private void checkNonExternalizeString() throws InvalidInputException {
3846 if (currentLine == null)
3848 parseTags(currentLine);
3850 private void parseTags(NLSLine line) throws InvalidInputException {
3851 String s = new String(getCurrentTokenSource());
3852 int pos = s.indexOf(TAG_PREFIX);
3853 int lineLength = line.size();
3855 int start = pos + TAG_PREFIX_LENGTH;
3856 int end = s.indexOf(TAG_POSTFIX, start);
3857 String index = s.substring(start, end);
3860 i = Integer.parseInt(index) - 1;
3861 // Tags are one based not zero based.
3862 } catch (NumberFormatException e) {
3863 i = -1; // we don't want to consider this as a valid NLS tag
3865 if (line.exists(i)) {
3868 pos = s.indexOf(TAG_PREFIX, start);
3870 this.nonNLSStrings = new StringLiteral[lineLength];
3871 int nonNLSCounter = 0;
3872 for (Iterator iterator = line.iterator(); iterator.hasNext();) {
3873 StringLiteral literal = (StringLiteral) iterator.next();
3874 if (literal != null) {
3875 this.nonNLSStrings[nonNLSCounter++] = literal;
3878 if (nonNLSCounter == 0) {
3879 this.nonNLSStrings = null;
3883 this.wasNonExternalizedStringLiteral = true;
3884 if (nonNLSCounter != lineLength) {
3885 System.arraycopy(this.nonNLSStrings, 0,
3886 (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0,
3891 public final void scanEscapeCharacter() throws InvalidInputException {
3892 // the string with "\\u" is a legal string of two chars \ and u
3893 //thus we use a direct access to the source (for regular cases).
3894 if (unicodeAsBackSlash) {
3895 // consume next character
3896 unicodeAsBackSlash = false;
3897 // if (((currentCharacter = source[currentPosition++]) == '\\') &&
3898 // (source[currentPosition] == 'u')) {
3899 // getNextUnicodeChar();
3901 if (withoutUnicodePtr != 0) {
3902 withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
3906 currentCharacter = source[currentPosition++];
3907 switch (currentCharacter) {
3909 currentCharacter = '\b';
3912 currentCharacter = '\t';
3915 currentCharacter = '\n';
3918 currentCharacter = '\f';
3921 currentCharacter = '\r';
3924 currentCharacter = '\"';
3927 currentCharacter = '\'';
3930 currentCharacter = '\\';
3933 // -----------octal escape--------------
3935 // OctalDigit OctalDigit
3936 // ZeroToThree OctalDigit OctalDigit
3937 int number = Character.getNumericValue(currentCharacter);
3938 if (number >= 0 && number <= 7) {
3939 boolean zeroToThreeNot = number > 3;
3940 if (Character.isDigit(currentCharacter = source[currentPosition++])) {
3941 int digit = Character.getNumericValue(currentCharacter);
3942 if (digit >= 0 && digit <= 7) {
3943 number = (number * 8) + digit;
3945 .isDigit(currentCharacter = source[currentPosition++])) {
3946 if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit
3947 // Digit --> ignore last character
3950 digit = Character.getNumericValue(currentCharacter);
3951 if (digit >= 0 && digit <= 7) { // has read \ZeroToThree
3952 // OctalDigit OctalDigit
3953 number = (number * 8) + digit;
3954 } else { // has read \ZeroToThree OctalDigit NonOctalDigit
3955 // --> ignore last character
3959 } else { // has read \OctalDigit NonDigit--> ignore last
3963 } else { // has read \OctalDigit NonOctalDigit--> ignore last
3967 } else { // has read \OctalDigit --> ignore last character
3971 throw new InvalidInputException(INVALID_ESCAPE);
3972 currentCharacter = (char) number;
3974 throw new InvalidInputException(INVALID_ESCAPE);
3977 // chech presence of task: tags
3978 public void checkTaskTag(int commentStart, int commentEnd) {
3979 // only look for newer task: tags
3980 if (this.foundTaskCount > 0
3981 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
3984 int foundTaskIndex = this.foundTaskCount;
3985 nextChar : for (int i = commentStart; i < commentEnd
3986 && i < this.eofPosition; i++) {
3988 char[] priority = null;
3989 // check for tag occurrence
3990 nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
3991 tag = this.taskTags[itag];
3992 priority = this.taskPriorities != null
3993 && itag < this.taskPriorities.length
3994 ? this.taskPriorities[itag]
3996 int tagLength = tag.length;
3997 for (int t = 0; t < tagLength; t++) {
3998 if (this.source[i + t] != tag[t])
4001 if (this.foundTaskTags == null) {
4002 this.foundTaskTags = new char[5][];
4003 this.foundTaskMessages = new char[5][];
4004 this.foundTaskPriorities = new char[5][];
4005 this.foundTaskPositions = new int[5][];
4006 } else if (this.foundTaskCount == this.foundTaskTags.length) {
4007 System.arraycopy(this.foundTaskTags, 0,
4008 this.foundTaskTags = new char[this.foundTaskCount * 2][], 0,
4009 this.foundTaskCount);
4010 System.arraycopy(this.foundTaskMessages, 0,
4011 this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0,
4012 this.foundTaskCount);
4013 System.arraycopy(this.foundTaskPriorities, 0,
4014 this.foundTaskPriorities = new char[this.foundTaskCount * 2][],
4015 0, this.foundTaskCount);
4016 System.arraycopy(this.foundTaskPositions, 0,
4017 this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0,
4018 this.foundTaskCount);
4020 this.foundTaskTags[this.foundTaskCount] = tag;
4021 this.foundTaskPriorities[this.foundTaskCount] = priority;
4022 this.foundTaskPositions[this.foundTaskCount] = new int[]{i,
4024 this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
4025 this.foundTaskCount++;
4026 i += tagLength - 1; // will be incremented when looping
4029 for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
4030 // retrieve message start and end positions
4031 int msgStart = this.foundTaskPositions[i][0]
4032 + this.foundTaskTags[i].length;
4033 int max_value = i + 1 < this.foundTaskCount
4034 ? this.foundTaskPositions[i + 1][0] - 1
4036 // at most beginning of next task
4037 if (max_value < msgStart)
4038 max_value = msgStart; // would only occur if tag is before EOF.
4041 for (int j = msgStart; j < max_value; j++) {
4042 if ((c = this.source[j]) == '\n' || c == '\r') {
4048 for (int j = max_value; j > msgStart; j--) {
4049 if ((c = this.source[j]) == '*') {
4057 if (msgStart == end)
4060 while (CharOperation.isWhitespace(source[end]) && msgStart <= end)
4062 while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end)
4064 // update the end position of the task
4065 this.foundTaskPositions[i][1] = end;
4066 // get the message source
4067 final int messageLength = end - msgStart + 1;
4068 char[] message = new char[messageLength];
4069 System.arraycopy(source, msgStart, message, 0, messageLength);
4070 this.foundTaskMessages[i] = message;