| 1 11 package org.eclipse.jdt.internal.core.util; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.core.compiler.IScanner; 15 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 16 import org.eclipse.jdt.core.compiler.InvalidInputException; 17 import org.eclipse.jdt.internal.compiler.CompilationResult; 18 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 19 import org.eclipse.jdt.internal.compiler.parser.NLSTag; 20 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 21 import org.eclipse.jdt.internal.compiler.util.Util; 22 23 public class PublicScanner implements IScanner, ITerminalSymbols { 24 25 27 35 public long sourceLevel; 36 public long complianceLevel; 37 38 public boolean useAssertAsAnIndentifier = false; 40 public boolean containsAssertKeyword = false; 42 43 public boolean useEnumAsAnIndentifier = false; 45 46 public boolean recordLineSeparator = false; 47 public char currentCharacter; 48 public int startPosition; 49 public int currentPosition; 50 public int initialPosition, eofPosition; 51 53 public boolean tokenizeComments = false; 54 public boolean tokenizeWhiteSpace = false; 55 56 public char source[]; 59 60 public char[] withoutUnicodeBuffer; 62 public int withoutUnicodePtr; public boolean unicodeAsBackSlash = false; 64 65 public boolean scanningFloatLiteral = false; 66 67 public final static int COMMENT_ARRAYS_SIZE = 30; 69 public int[] commentStops = new int[COMMENT_ARRAYS_SIZE]; 70 public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE]; 71 public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE]; 72 public int commentPtr = -1; protected int lastCommentLinePosition = -1; 74 75 public char[][] foundTaskTags = null; 77 public char[][] foundTaskMessages; 78 public char[][] foundTaskPriorities = null; 79 public int[][] foundTaskPositions; 80 public int foundTaskCount = 0; 81 public char[][] taskTags = null; 82 public char[][] taskPriorities = null; 83 public boolean isTaskCaseSensitive = true; 84 85 public boolean diet = false; 87 88 public int[] lineEnds = new int[250]; 91 public int linePtr = -1; 92 public boolean wasAcr = false; 93 94 public static final String END_OF_SOURCE = "End_Of_Source"; 96 public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; public static final String INVALID_ESCAPE = "Invalid_Escape"; public static final String INVALID_INPUT = "Invalid_Input"; public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; public static final String INVALID_FLOAT = "Invalid_Float_Literal"; public static final String INVALID_LOW_SURROGATE = "Invalid_Low_Surrogate"; public static final String INVALID_HIGH_SURROGATE = "Invalid_High_Surrogate"; 106 public static final String NULL_SOURCE_STRING = "Null_Source_String"; public static final String UNTERMINATED_STRING = "Unterminated_String"; public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; public static final String INVALID_DIGIT = "Invalid_Digit"; private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY; 112 113 static final char[] charArray_a = new char[] {'a'}, 115 charArray_b = new char[] {'b'}, 116 charArray_c = new char[] {'c'}, 117 charArray_d = new char[] {'d'}, 118 charArray_e = new char[] {'e'}, 119 charArray_f = new char[] {'f'}, 120 charArray_g = new char[] {'g'}, 121 charArray_h = new char[] {'h'}, 122 charArray_i = new char[] {'i'}, 123 charArray_j = new char[] {'j'}, 124 charArray_k = new char[] {'k'}, 125 charArray_l = new char[] {'l'}, 126 charArray_m = new char[] {'m'}, 127 charArray_n = new char[] {'n'}, 128 charArray_o = new char[] {'o'}, 129 charArray_p = new char[] {'p'}, 130 charArray_q = new char[] {'q'}, 131 charArray_r = new char[] {'r'}, 132 charArray_s = new char[] {'s'}, 133 charArray_t = new char[] {'t'}, 134 charArray_u = new char[] {'u'}, 135 charArray_v = new char[] {'v'}, 136 charArray_w = new char[] {'w'}, 137 charArray_x = new char[] {'x'}, 138 charArray_y = new char[] {'y'}, 139 charArray_z = new char[] {'z'}; 140 141 static final char[] initCharArray = 142 new char[] {'\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000'}; 143 static final int TableSize = 30, InternalTableSize = 6; 145 public static final int OptimizedLength = 7; 146 public final char[][][][] charArray_length = 147 new char[OptimizedLength][TableSize][InternalTableSize][]; 148 public static final char[] TAG_PREFIX= "//$NON-NLS-".toCharArray(); public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length; 151 public static final char TAG_POSTFIX= '$'; 152 public static final int TAG_POSTFIX_LENGTH= 1; 153 private NLSTag[] nlsTags = null; 154 protected int nlsTagsPtr; 155 public boolean checkNonExternalizedStringLiterals; 156 157 public boolean returnOnlyGreater = false; 159 160 { 161 for (int i = 0; i < 6; i++) { 162 for (int j = 0; j < TableSize; j++) { 163 for (int k = 0; k < InternalTableSize; k++) { 164 this.charArray_length[i][j][k] = initCharArray; 165 } 166 } 167 } 168 } 169 int newEntry2 = 0, 170 newEntry3 = 0, 171 newEntry4 = 0, 172 newEntry5 = 0, 173 newEntry6 = 0; 174 public boolean insideRecovery = false; 175 176 public static final int RoundBracket = 0; 177 public static final int SquareBracket = 1; 178 public static final int CurlyBracket = 2; 179 public static final int BracketKinds = 3; 180 181 public static final int LOW_SURROGATE_MIN_VALUE = 0xDC00; 183 public static final int HIGH_SURROGATE_MIN_VALUE = 0xD800; 184 public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF; 185 public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF; 186 187 public PublicScanner() { 188 this(false , false , false , ClassFileConstants.JDK1_3 , null, null, true ); 189 } 190 191 public PublicScanner( 192 boolean tokenizeComments, 193 boolean tokenizeWhiteSpace, 194 boolean checkNonExternalizedStringLiterals, 195 long sourceLevel, 196 long complianceLevel, 197 char[][] taskTags, 198 char[][] taskPriorities, 199 boolean isTaskCaseSensitive) { 200 201 this.eofPosition = Integer.MAX_VALUE; 202 this.tokenizeComments = tokenizeComments; 203 this.tokenizeWhiteSpace = tokenizeWhiteSpace; 204 this.sourceLevel = sourceLevel; 205 this.complianceLevel = complianceLevel; 206 this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals; 207 this.taskTags = taskTags; 208 this.taskPriorities = taskPriorities; 209 this.isTaskCaseSensitive = isTaskCaseSensitive; 210 } 211 212 public PublicScanner( 213 boolean tokenizeComments, 214 boolean tokenizeWhiteSpace, 215 boolean checkNonExternalizedStringLiterals, 216 long sourceLevel, 217 char[][] taskTags, 218 char[][] taskPriorities, 219 boolean isTaskCaseSensitive) { 220 221 this( 222 tokenizeComments, 223 tokenizeWhiteSpace, 224 checkNonExternalizedStringLiterals, 225 sourceLevel, 226 sourceLevel, 227 taskTags, 228 taskPriorities, 229 isTaskCaseSensitive); 230 } 231 232 public final boolean atEnd() { 233 236 return this.eofPosition <= this.currentPosition; 237 } 238 239 public void checkTaskTag(int commentStart, int commentEnd) throws InvalidInputException { 242 char[] src = this.source; 243 244 if (this.foundTaskCount > 0 246 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { 247 return; 248 } 249 int foundTaskIndex = this.foundTaskCount; 250 char previous = src[commentStart+1]; for ( 252 int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) { 253 char[] tag = null; 254 char[] priority = null; 255 if (previous != '@') { 257 nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) { 258 tag = this.taskTags[itag]; 259 int tagLength = tag.length; 260 if (tagLength == 0) continue nextTag; 261 262 if (ScannerHelper.isJavaIdentifierStart(tag[0])) { 264 if (ScannerHelper.isJavaIdentifierPart(previous)) { 265 continue nextTag; 266 } 267 } 268 269 for (int t = 0; t < tagLength; t++) { 270 char sc, tc; 271 int x = i+t; 272 if (x >= this.eofPosition || x >= commentEnd) continue nextTag; 273 if ((sc = src[i + t]) != (tc = tag[t])) { if (this.isTaskCaseSensitive || (ScannerHelper.toLowerCase(sc) != ScannerHelper.toLowerCase(tc))) { continue nextTag; 276 } 277 } 278 } 279 if (i+tagLength < commentEnd && ScannerHelper.isJavaIdentifierPart(src[i+tagLength-1])) { 281 if (ScannerHelper.isJavaIdentifierPart(src[i + tagLength])) 282 continue nextTag; 283 } 284 if (this.foundTaskTags == null) { 285 this.foundTaskTags = new char[5][]; 286 this.foundTaskMessages = new char[5][]; 287 this.foundTaskPriorities = new char[5][]; 288 this.foundTaskPositions = new int[5][]; 289 } else if (this.foundTaskCount == this.foundTaskTags.length) { 290 System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); 291 System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); 292 System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); 293 System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount); 294 } 295 296 priority = this.taskPriorities != null && itag < this.taskPriorities.length 297 ? this.taskPriorities[itag] 298 : null; 299 300 this.foundTaskTags[this.foundTaskCount] = tag; 301 this.foundTaskPriorities[this.foundTaskCount] = priority; 302 this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; 303 this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; 304 this.foundTaskCount++; 305 i += tagLength - 1; break nextTag; 307 } 308 } 309 previous = src[i]; 310 } 311 boolean containsEmptyTask = false; 312 for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { 313 int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; 315 int max_value = i + 1 < this.foundTaskCount 316 ? this.foundTaskPositions[i + 1][0] - 1 317 : commentEnd - 1; 318 if (max_value < msgStart) { 320 max_value = msgStart; } 322 int end = -1; 323 char c; 324 for (int j = msgStart; j < max_value; j++) { 325 if ((c = src[j]) == '\n' || c == '\r') { 326 end = j - 1; 327 break; 328 } 329 } 330 if (end == -1) { 331 for (int j = max_value; j > msgStart; j--) { 332 if ((c = src[j]) == '*') { 333 end = j - 1; 334 break; 335 } 336 } 337 if (end == -1) 338 end = max_value; 339 } 340 if (msgStart == end) { 341 containsEmptyTask = true; 344 continue; 345 } 346 while (CharOperation.isWhitespace(src[end]) && msgStart <= end) 348 end--; 349 while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end) 350 msgStart++; 351 this.foundTaskPositions[i][1] = end; 353 final int messageLength = end - msgStart + 1; 355 char[] message = new char[messageLength]; 356 System.arraycopy(src, msgStart, message, 0, messageLength); 357 this.foundTaskMessages[i] = message; 358 } 359 if (containsEmptyTask) { 360 for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) { 361 if (this.foundTaskMessages[i].length == 0) { 362 loop: for (int j = i + 1; j < max; j++) { 363 if (this.foundTaskMessages[j].length != 0) { 364 this.foundTaskMessages[i] = this.foundTaskMessages[j]; 365 this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1]; 366 break loop; 367 } 368 } 369 } 370 } 371 } 372 } 373 374 public char[] getCurrentIdentifierSource() { 375 377 char[] result; 378 if (this.withoutUnicodePtr != 0) { 379 System.arraycopy( 381 this.withoutUnicodeBuffer, 382 1, 383 result = new char[this.withoutUnicodePtr], 384 0, 385 this.withoutUnicodePtr); 386 } else { 387 int length = this.currentPosition - this.startPosition; 388 if (length == this.eofPosition) return this.source; 389 switch (length) { case 1 : 391 return optimizedCurrentTokenSource1(); 392 case 2 : 393 return optimizedCurrentTokenSource2(); 394 case 3 : 395 return optimizedCurrentTokenSource3(); 396 case 4 : 397 return optimizedCurrentTokenSource4(); 398 case 5 : 399 return optimizedCurrentTokenSource5(); 400 case 6 : 401 return optimizedCurrentTokenSource6(); 402 } 403 System.arraycopy(this.source, this.startPosition, result = new char[length], 0, length); 405 } 406 return result; 408 } 409 public int getCurrentTokenEndPosition(){ 410 return this.currentPosition - 1; 411 } 412 public char[] getCurrentTokenSource() { 413 415 char[] result; 416 if (this.withoutUnicodePtr != 0) 417 System.arraycopy( 419 this.withoutUnicodeBuffer, 420 1, 421 result = new char[this.withoutUnicodePtr], 422 0, 423 this.withoutUnicodePtr); 424 else { 425 int length; 426 System.arraycopy( 427 this.source, 428 this.startPosition, 429 result = new char[length = this.currentPosition - this.startPosition], 430 0, 431 length); 432 } 433 return result; 434 } 435 public final String getCurrentTokenString() { 436 438 if (this.withoutUnicodePtr != 0) { 439 return new String ( 441 this.withoutUnicodeBuffer, 442 1, 443 this.withoutUnicodePtr); 444 } 445 return new String ( 446 this.source, 447 this.startPosition, 448 this.currentPosition - this.startPosition); 449 } 450 public char[] getCurrentTokenSourceString() { 451 454 char[] result; 455 if (this.withoutUnicodePtr != 0) 456 System.arraycopy(this.withoutUnicodeBuffer, 2, 458 result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2); 460 else { 461 int length; 462 System.arraycopy( 463 this.source, 464 this.startPosition + 1, 465 result = new char[length = this.currentPosition - this.startPosition - 2], 466 0, 467 length); 468 } 469 return result; 470 } 471 public final String getCurrentStringLiteral() { 472 475 if (this.withoutUnicodePtr != 0) 476 return new String (this.withoutUnicodeBuffer, 2, this.withoutUnicodePtr - 2); 479 else { 480 return new String (this.source, this.startPosition + 1, this.currentPosition - this.startPosition - 2); 481 } 482 } 483 public final char[] getRawTokenSource() { 484 int length = this.currentPosition - this.startPosition; 485 char[] tokenSource = new char[length]; 486 System.arraycopy(this.source, this.startPosition, tokenSource, 0, length); 487 return tokenSource; 488 } 489 490 public final char[] getRawTokenSourceEnd() { 491 int length = this.eofPosition - this.currentPosition - 1; 492 char[] sourceEnd = new char[length]; 493 System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length); 494 return sourceEnd; 495 } 496 497 public int getCurrentTokenStartPosition(){ 498 return this.startPosition; 499 } 500 508 public final int getLineEnd(int lineNumber) { 509 510 if (this.lineEnds == null || this.linePtr == -1) 511 return -1; 512 if (lineNumber > this.lineEnds.length+1) 513 return -1; 514 if (lineNumber <= 0) 515 return -1; 516 if (lineNumber == this.lineEnds.length + 1) 517 return this.eofPosition; 518 return this.lineEnds[lineNumber-1]; } 520 521 public final int[] getLineEnds() { 522 if (this.linePtr == -1) { 524 return EMPTY_LINE_ENDS; 525 } 526 int[] copy; 527 System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1); 528 return copy; 529 } 530 531 544 public final int getLineStart(int lineNumber) { 545 546 if (this.lineEnds == null || this.linePtr == -1) 547 return -1; 548 if (lineNumber > this.lineEnds.length + 1) 549 return -1; 550 if (lineNumber <= 0) 551 return -1; 552 553 if (lineNumber == 1) 554 return this.initialPosition; 555 return this.lineEnds[lineNumber-2]+1; } 557 public final int getNextChar() { 558 try { 559 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') 560 && (this.source[this.currentPosition] == 'u')) { 561 getNextUnicodeChar(); 562 } else { 563 this.unicodeAsBackSlash = false; 564 if (this.withoutUnicodePtr != 0) { 565 unicodeStore(); 566 } 567 } 568 return this.currentCharacter; 569 } catch (IndexOutOfBoundsException e) { 570 return -1; 571 } catch(InvalidInputException e) { 572 return -1; 573 } 574 } 575 public final int getNextCharWithBoundChecks() { 576 if (this.currentPosition >= this.eofPosition) { 577 return -1; 578 } 579 this.currentCharacter = this.source[this.currentPosition++]; 580 if (this.currentPosition >= this.eofPosition) { 581 this.unicodeAsBackSlash = false; 582 if (this.withoutUnicodePtr != 0) { 583 unicodeStore(); 584 } 585 return this.currentCharacter; 586 } 587 if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') { 588 try { 589 getNextUnicodeChar(); 590 } catch (InvalidInputException e) { 591 return -1; 592 } 593 } else { 594 this.unicodeAsBackSlash = false; 595 if (this.withoutUnicodePtr != 0) { 596 unicodeStore(); 597 } 598 } 599 return this.currentCharacter; 600 } 601 public final boolean getNextChar(char testedChar) { 602 610 612 if (this.currentPosition >= this.eofPosition) { this.unicodeAsBackSlash = false; 614 return false; 615 } 616 617 int temp = this.currentPosition; 618 try { 619 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') 620 && (this.source[this.currentPosition] == 'u')) { 621 getNextUnicodeChar(); 622 if (this.currentCharacter != testedChar) { 623 this.currentPosition = temp; 624 this.withoutUnicodePtr--; 625 return false; 626 } 627 return true; 628 } else { 630 if (this.currentCharacter != testedChar) { 631 this.currentPosition = temp; 632 return false; 633 } 634 this.unicodeAsBackSlash = false; 635 if (this.withoutUnicodePtr != 0) 636 unicodeStore(); 637 return true; 638 } 639 } catch (IndexOutOfBoundsException e) { 640 this.unicodeAsBackSlash = false; 641 this.currentPosition = temp; 642 return false; 643 } catch(InvalidInputException e) { 644 this.unicodeAsBackSlash = false; 645 this.currentPosition = temp; 646 return false; 647 } 648 } 649 public final int getNextChar(char testedChar1, char testedChar2) { 650 659 if (this.currentPosition >= this.eofPosition) return -1; 662 663 int temp = this.currentPosition; 664 try { 665 int result; 666 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') 667 && (this.source[this.currentPosition] == 'u')) { 668 getNextUnicodeChar(); 669 if (this.currentCharacter == testedChar1) { 670 result = 0; 671 } else if (this.currentCharacter == testedChar2) { 672 result = 1; 673 } else { 674 this.currentPosition = temp; 675 this.withoutUnicodePtr--; 676 result = -1; 677 } 678 return result; 679 } else { 680 if (this.currentCharacter == testedChar1) { 681 result = 0; 682 } else if (this.currentCharacter == testedChar2) { 683 result = 1; 684 } else { 685 this.currentPosition = temp; 686 return -1; 687 } 688 689 if (this.withoutUnicodePtr != 0) 690 unicodeStore(); 691 return result; 692 } 693 } catch (IndexOutOfBoundsException e) { 694 this.currentPosition = temp; 695 return -1; 696 } catch(InvalidInputException e) { 697 this.currentPosition = temp; 698 return -1; 699 } 700 } 701 public final boolean getNextCharAsDigit() throws InvalidInputException { 702 710 if (this.currentPosition >= this.eofPosition) return false; 713 714 int temp = this.currentPosition; 715 try { 716 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') 717 && (this.source[this.currentPosition] == 'u')) { 718 getNextUnicodeChar(); 719 if (!ScannerHelper.isDigit(this.currentCharacter)) { 720 this.currentPosition = temp; 721 this.withoutUnicodePtr--; 722 return false; 723 } 724 return true; 725 } else { 726 if (!ScannerHelper.isDigit(this.currentCharacter)) { 727 this.currentPosition = temp; 728 return false; 729 } 730 if (this.withoutUnicodePtr != 0) 731 unicodeStore(); 732 return true; 733 } 734 } catch (IndexOutOfBoundsException e) { 735 this.currentPosition = temp; 736 return false; 737 } catch(InvalidInputException e) { 738 this.currentPosition = temp; 739 return false; 740 } 741 } 742 public final boolean getNextCharAsDigit(int radix) { 743 751 if (this.currentPosition >= this.eofPosition) return false; 754 755 int temp = this.currentPosition; 756 try |