| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.util; |
| |
| import java.util.Iterator; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.core.compiler.IScanner; |
| import org.eclipse.jdt.core.compiler.ITerminalSymbols; |
| import org.eclipse.jdt.core.compiler.InvalidInputException; |
| import org.eclipse.jdt.internal.compiler.CompilationResult; |
| import org.eclipse.jdt.internal.compiler.ast.StringLiteral; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.parser.NLSLine; |
| import org.eclipse.jdt.internal.compiler.parser.Scanner; |
| import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; |
| |
| public class PublicScanner implements IScanner, ITerminalSymbols { |
| |
| //public int newIdentCount = 0; |
| |
| /* APIs ares |
| - getNextToken() which return the current type of the token |
| (this value is not memorized by the scanner) |
| - getCurrentTokenSource() which provides with the token "REAL" source |
| (aka all unicode have been transformed into a correct char) |
| - sourceStart gives the position into the stream |
| - currentPosition-1 gives the sourceEnd position into the stream |
| */ |
| protected long sourceLevel; |
| protected long complianceLevel; |
| |
| // 1.4 feature |
| public boolean useAssertAsAnIndentifier = false; |
| //flag indicating if processed source contains occurrences of keyword assert |
| public boolean containsAssertKeyword = false; |
| |
| // 1.5 feature |
| public boolean useEnumAsAnIndentifier = false; |
| |
| public boolean recordLineSeparator = false; |
| public char currentCharacter; |
| public int startPosition; |
| public int currentPosition; |
| public int initialPosition, eofPosition; |
| // after this position eof are generated instead of real token from the source |
| |
| public boolean tokenizeComments = false; |
| public boolean tokenizeWhiteSpace = false; |
| |
| //source should be viewed as a window (aka a part) |
| //of a entire very large stream |
| public char source[]; |
| |
| //unicode support |
| public char[] withoutUnicodeBuffer; |
| public int withoutUnicodePtr; //when == 0 ==> no unicode in the current token |
| public boolean unicodeAsBackSlash = false; |
| |
| public boolean scanningFloatLiteral = false; |
| |
| //support for /** comments |
| public static int COMMENT_ARRAYS_SIZE = 30; |
| public int[] commentStops = new int[COMMENT_ARRAYS_SIZE]; |
| public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE]; |
| public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE]; |
| public int commentPtr = -1; // no comment test with commentPtr value -1 |
| protected int lastCommentLinePosition = -1; |
| |
| // task tag support |
| public char[][] foundTaskTags = null; |
| public char[][] foundTaskMessages; |
| public char[][] foundTaskPriorities = null; |
| public int[][] foundTaskPositions; |
| public int foundTaskCount = 0; |
| public char[][] taskTags = null; |
| public char[][] taskPriorities = null; |
| public boolean isTaskCaseSensitive = true; |
| |
| //diet parsing support - jump over some method body when requested |
| public boolean diet = false; |
| |
| //support for the poor-line-debuggers .... |
| //remember the position of the cr/lf |
| public int[] lineEnds = new int[250]; |
| public int linePtr = -1; |
| public boolean wasAcr = false; |
| |
| public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$ |
| |
| public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$ |
| public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$ |
| public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$ |
| public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$ |
| public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$ |
| public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$ |
| public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$ |
| public static final String INVALID_LOW_SURROGATE = "Invalid_Low_Surrogate"; //$NON-NLS-1$ |
| public static final String INVALID_HIGH_SURROGATE = "Invalid_High_Surrogate"; //$NON-NLS-1$ |
| |
| public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$ |
| public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$ |
| public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$ |
| public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$ |
| public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$ |
| private static final int[] EMPTY_LINE_ENDS = new int[0]; |
| |
| //----------------optimized identifier managment------------------ |
| static final char[] charArray_a = new char[] {'a'}, |
| charArray_b = new char[] {'b'}, |
| charArray_c = new char[] {'c'}, |
| charArray_d = new char[] {'d'}, |
| charArray_e = new char[] {'e'}, |
| charArray_f = new char[] {'f'}, |
| charArray_g = new char[] {'g'}, |
| charArray_h = new char[] {'h'}, |
| charArray_i = new char[] {'i'}, |
| charArray_j = new char[] {'j'}, |
| charArray_k = new char[] {'k'}, |
| charArray_l = new char[] {'l'}, |
| charArray_m = new char[] {'m'}, |
| charArray_n = new char[] {'n'}, |
| charArray_o = new char[] {'o'}, |
| charArray_p = new char[] {'p'}, |
| charArray_q = new char[] {'q'}, |
| charArray_r = new char[] {'r'}, |
| charArray_s = new char[] {'s'}, |
| charArray_t = new char[] {'t'}, |
| charArray_u = new char[] {'u'}, |
| charArray_v = new char[] {'v'}, |
| charArray_w = new char[] {'w'}, |
| charArray_x = new char[] {'x'}, |
| charArray_y = new char[] {'y'}, |
| charArray_z = new char[] {'z'}; |
| |
| static final char[] initCharArray = |
| new char[] {'\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000'}; |
| static final int TableSize = 30, InternalTableSize = 6; //30*6 =210 entries |
| |
| public final static int MAX_OBVIOUS = 128; |
| static final int[] ObviousIdentCharNatures = new int[MAX_OBVIOUS]; |
| public final static int C_LETTER = 4; |
| public final static int C_DIGIT = 3; |
| public final static int C_SEPARATOR = 2; |
| public final static int C_SPACE = 1; |
| static { |
| for (int i = '0'; i <= '9'; i++) |
| ObviousIdentCharNatures[i] = C_DIGIT; |
| |
| for (int i = 'a'; i <= 'z'; i++) |
| ObviousIdentCharNatures[i] = C_LETTER; |
| for (int i = 'A'; i <= 'Z'; i++) |
| ObviousIdentCharNatures[i] = C_LETTER; |
| ObviousIdentCharNatures['_'] = C_LETTER; |
| ObviousIdentCharNatures['$'] = C_LETTER; |
| |
| ObviousIdentCharNatures[10] = C_SPACE; // \ u000a: LINE FEED |
| ObviousIdentCharNatures[12] = C_SPACE; // \ u000c: FORM FEED |
| ObviousIdentCharNatures[13] = C_SPACE; // \ u000d: CARRIAGE RETURN |
| ObviousIdentCharNatures[32] = C_SPACE; // \ u0020: SPACE |
| ObviousIdentCharNatures[ 9] = C_SPACE; // \ u0009: HORIZONTAL TABULATION |
| |
| ObviousIdentCharNatures['.'] = C_SEPARATOR; |
| ObviousIdentCharNatures[':'] = C_SEPARATOR; |
| ObviousIdentCharNatures[';'] = C_SEPARATOR; |
| ObviousIdentCharNatures[','] = C_SEPARATOR; |
| ObviousIdentCharNatures['['] = C_SEPARATOR; |
| ObviousIdentCharNatures[']'] = C_SEPARATOR; |
| ObviousIdentCharNatures['('] = C_SEPARATOR; |
| ObviousIdentCharNatures[')'] = C_SEPARATOR; |
| ObviousIdentCharNatures['{'] = C_SEPARATOR; |
| ObviousIdentCharNatures['}'] = C_SEPARATOR; |
| ObviousIdentCharNatures['+'] = C_SEPARATOR; |
| ObviousIdentCharNatures['-'] = C_SEPARATOR; |
| ObviousIdentCharNatures['*'] = C_SEPARATOR; |
| ObviousIdentCharNatures['/'] = C_SEPARATOR; |
| ObviousIdentCharNatures['='] = C_SEPARATOR; |
| ObviousIdentCharNatures['&'] = C_SEPARATOR; |
| ObviousIdentCharNatures['|'] = C_SEPARATOR; |
| ObviousIdentCharNatures['?'] = C_SEPARATOR; |
| ObviousIdentCharNatures['<'] = C_SEPARATOR; |
| ObviousIdentCharNatures['>'] = C_SEPARATOR; |
| ObviousIdentCharNatures['!'] = C_SEPARATOR; |
| ObviousIdentCharNatures['%'] = C_SEPARATOR; |
| ObviousIdentCharNatures['^'] = C_SEPARATOR; |
| ObviousIdentCharNatures['~'] = C_SEPARATOR; |
| ObviousIdentCharNatures['"'] = C_SEPARATOR; |
| ObviousIdentCharNatures['\''] = C_SEPARATOR; |
| } |
| |
| public static final int OptimizedLength = 7; |
| public /*static*/ final char[][][][] charArray_length = |
| new char[OptimizedLength][TableSize][InternalTableSize][]; |
| // support for detecting non-externalized string literals |
| public NLSLine currentLine= null; |
| public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$ |
| public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length(); |
| public static final String TAG_POSTFIX= "$"; //$NON-NLS-1$ |
| public static final int TAG_POSTFIX_LENGTH= TAG_POSTFIX.length(); |
| public StringLiteral[] nonNLSStrings = null; |
| public boolean checkNonExternalizedStringLiterals = false; |
| public boolean wasNonExternalizedStringLiteral = false; |
| |
| // generic support |
| public boolean returnOnlyGreater = false; |
| |
| /*static*/ { |
| for (int i = 0; i < 6; i++) { |
| for (int j = 0; j < TableSize; j++) { |
| for (int k = 0; k < InternalTableSize; k++) { |
| this.charArray_length[i][j][k] = initCharArray; |
| } |
| } |
| } |
| } |
| /*static*/ int newEntry2 = 0, |
| newEntry3 = 0, |
| newEntry4 = 0, |
| newEntry5 = 0, |
| newEntry6 = 0; |
| |
| public static final int RoundBracket = 0; |
| public static final int SquareBracket = 1; |
| public static final int CurlyBracket = 2; |
| public static final int BracketKinds = 3; |
| |
| // extended unicode support |
| public static final int LOW_SURROGATE_MIN_VALUE = 0xDC00; |
| public static final int HIGH_SURROGATE_MIN_VALUE = 0xD800; |
| public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF; |
| public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF; |
| |
| public PublicScanner() { |
| this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/); |
| } |
| |
| public PublicScanner( |
| boolean tokenizeComments, |
| boolean tokenizeWhiteSpace, |
| boolean checkNonExternalizedStringLiterals, |
| long sourceLevel, |
| long complianceLevel, |
| char[][] taskTags, |
| char[][] taskPriorities, |
| boolean isTaskCaseSensitive) { |
| |
| this.eofPosition = Integer.MAX_VALUE; |
| this.tokenizeComments = tokenizeComments; |
| this.tokenizeWhiteSpace = tokenizeWhiteSpace; |
| this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals; |
| this.sourceLevel = sourceLevel; |
| this.complianceLevel = complianceLevel; |
| this.taskTags = taskTags; |
| this.taskPriorities = taskPriorities; |
| this.isTaskCaseSensitive = isTaskCaseSensitive; |
| } |
| |
| public PublicScanner( |
| boolean tokenizeComments, |
| boolean tokenizeWhiteSpace, |
| boolean checkNonExternalizedStringLiterals, |
| long sourceLevel, |
| char[][] taskTags, |
| char[][] taskPriorities, |
| boolean isTaskCaseSensitive) { |
| |
| this.eofPosition = Integer.MAX_VALUE; |
| this.tokenizeComments = tokenizeComments; |
| this.tokenizeWhiteSpace = tokenizeWhiteSpace; |
| this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals; |
| this.sourceLevel = sourceLevel; |
| this.complianceLevel = sourceLevel; |
| this.taskTags = taskTags; |
| this.taskPriorities = taskPriorities; |
| this.isTaskCaseSensitive = isTaskCaseSensitive; |
| } |
| |
| public final boolean atEnd() { |
| // This code is not relevant if source is |
| // Only a part of the real stream input |
| |
| return this.source.length == this.currentPosition; |
| } |
| |
| protected void checkNonExternalizedString() { |
| if (this.currentLine == null) |
| return; |
| parseTags(this.currentLine); |
| } |
| |
| // chech presence of task: tags |
| // TODO (frederic) see if we need to take unicode characters into account... |
| public void checkTaskTag(int commentStart, int commentEnd) throws InvalidInputException { |
| char[] src = this.source; |
| |
| // only look for newer task: tags |
| if (this.foundTaskCount > 0 |
| && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { |
| return; |
| } |
| int foundTaskIndex = this.foundTaskCount; |
| char previous = src[commentStart+1]; // should be '*' or '/' |
| nextChar : for ( |
| int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) { |
| char[] tag = null; |
| char[] priority = null; |
| // check for tag occurrence only if not ambiguous with javadoc tag |
| if (previous != '@') { |
| nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) { |
| tag = this.taskTags[itag]; |
| int tagLength = tag.length; |
| if (tagLength == 0) continue nextTag; |
| |
| // ensure tag is not leaded with letter if tag starts with a letter |
| if (Character.isJavaIdentifierStart(tag[0])) { |
| if (Character.isJavaIdentifierPart(previous)) { |
| continue nextTag; |
| } |
| } |
| |
| for (int t = 0; t < tagLength; t++) { |
| char sc, tc; |
| int x = i+t; |
| if (x >= this.eofPosition || x >= commentEnd) continue nextTag; |
| if ((sc = src[i + t]) != (tc = tag[t])) { // case sensitive check |
| if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) { // case insensitive check |
| continue nextTag; |
| } |
| } |
| } |
| // ensure tag is not followed with letter if tag finishes with a letter |
| if (i+tagLength < commentEnd && Character.isJavaIdentifierPart(src[i+tagLength-1])) { |
| if (Character.isJavaIdentifierPart(src[i + tagLength])) |
| continue nextTag; |
| } |
| if (this.foundTaskTags == null) { |
| this.foundTaskTags = new char[5][]; |
| this.foundTaskMessages = new char[5][]; |
| this.foundTaskPriorities = new char[5][]; |
| this.foundTaskPositions = new int[5][]; |
| } else if (this.foundTaskCount == this.foundTaskTags.length) { |
| System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); |
| System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); |
| System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); |
| System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount); |
| } |
| |
| priority = this.taskPriorities != null && itag < this.taskPriorities.length |
| ? this.taskPriorities[itag] |
| : null; |
| |
| this.foundTaskTags[this.foundTaskCount] = tag; |
| this.foundTaskPriorities[this.foundTaskCount] = priority; |
| this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; |
| this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; |
| this.foundTaskCount++; |
| i += tagLength - 1; // will be incremented when looping |
| break nextTag; |
| } |
| } |
| previous = src[i]; |
| } |
| for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { |
| // retrieve message start and end positions |
| int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; |
| int max_value = i + 1 < this.foundTaskCount |
| ? this.foundTaskPositions[i + 1][0] - 1 |
| : commentEnd - 1; |
| // at most beginning of next task |
| if (max_value < msgStart) { |
| max_value = msgStart; // would only occur if tag is before EOF. |
| } |
| int end = -1; |
| char c; |
| for (int j = msgStart; j < max_value; j++) { |
| if ((c = src[j]) == '\n' || c == '\r') { |
| end = j - 1; |
| break; |
| } |
| } |
| if (end == -1) { |
| for (int j = max_value; j > msgStart; j--) { |
| if ((c = src[j]) == '*') { |
| end = j - 1; |
| break; |
| } |
| } |
| if (end == -1) |
| end = max_value; |
| } |
| if (msgStart == end) |
| continue; // empty |
| // trim the message |
| while (CharOperation.isWhitespace(src[end]) && msgStart <= end) |
| end--; |
| while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end) |
| msgStart++; |
| // update the end position of the task |
| this.foundTaskPositions[i][1] = end; |
| // get the message source |
| final int messageLength = end - msgStart + 1; |
| char[] message = new char[messageLength]; |
| System.arraycopy(src, msgStart, message, 0, messageLength); |
| this.foundTaskMessages[i] = message; |
| } |
| } |
| |
| public char[] getCurrentIdentifierSource() { |
| //return the token REAL source (aka unicodes are precomputed) |
| |
| char[] result; |
| if (this.withoutUnicodePtr != 0) { |
| //0 is used as a fast test flag so the real first char is in position 1 |
| System.arraycopy( |
| this.withoutUnicodeBuffer, |
| 1, |
| result = new char[this.withoutUnicodePtr], |
| 0, |
| this.withoutUnicodePtr); |
| } else { |
| int length = this.currentPosition - this.startPosition; |
| if (length == this.source.length) return this.source; |
| switch (length) { // see OptimizedLength |
| case 1 : |
| return optimizedCurrentTokenSource1(); |
| case 2 : |
| return optimizedCurrentTokenSource2(); |
| case 3 : |
| return optimizedCurrentTokenSource3(); |
| case 4 : |
| return optimizedCurrentTokenSource4(); |
| case 5 : |
| return optimizedCurrentTokenSource5(); |
| case 6 : |
| return optimizedCurrentTokenSource6(); |
| } |
| //no optimization |
| System.arraycopy(this.source, this.startPosition, result = new char[length], 0, length); |
| } |
| //newIdentCount++; |
| return result; |
| } |
| public int getCurrentTokenEndPosition(){ |
| return this.currentPosition - 1; |
| } |
| public final char[] getCurrentTokenSource() { |
| // Return the token REAL source (aka unicodes are precomputed) |
| |
| char[] result; |
| if (this.withoutUnicodePtr != 0) |
| // 0 is used as a fast test flag so the real first char is in position 1 |
| System.arraycopy( |
| this.withoutUnicodeBuffer, |
| 1, |
| result = new char[this.withoutUnicodePtr], |
| 0, |
| this.withoutUnicodePtr); |
| else { |
| int length; |
| System.arraycopy( |
| this.source, |
| this.startPosition, |
| result = new char[length = this.currentPosition - this.startPosition], |
| 0, |
| length); |
| } |
| return result; |
| } |
| public final String getCurrentTokenString() { |
| // Return current token as a string |
| |
| if (this.withoutUnicodePtr != 0) { |
| // 0 is used as a fast test flag so the real first char is in position 1 |
| return new String( |
| this.withoutUnicodeBuffer, |
| 1, |
| this.withoutUnicodePtr); |
| } |
| return new String( |
| this.source, |
| this.startPosition, |
| this.currentPosition - this.startPosition); |
| } |
| public final char[] getCurrentTokenSourceString() { |
| //return the token REAL source (aka unicodes are precomputed). |
| //REMOVE the two " that are at the beginning and the end. |
| |
| char[] result; |
| if (this.withoutUnicodePtr != 0) |
| //0 is used as a fast test flag so the real first char is in position 1 |
| System.arraycopy(this.withoutUnicodeBuffer, 2, |
| //2 is 1 (real start) + 1 (to jump over the ") |
| result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2); |
| else { |
| int length; |
| System.arraycopy( |
| this.source, |
| this.startPosition + 1, |
| result = new char[length = this.currentPosition - this.startPosition - 2], |
| 0, |
| length); |
| } |
| return result; |
| } |
| public final String getCurrentStringLiteral() { |
| //return the token REAL source (aka unicodes are precomputed). |
| //REMOVE the two " that are at the beginning and the end. |
| |
| if (this.withoutUnicodePtr != 0) |
| //0 is used as a fast test flag so the real first char is in position 1 |
| //2 is 1 (real start) + 1 (to jump over the ") |
| return new String(this.withoutUnicodeBuffer, 2, this.withoutUnicodePtr - 2); |
| else { |
| return new String(this.source, this.startPosition + 1, this.currentPosition - this.startPosition - 2); |
| } |
| } |
| public final char[] getRawTokenSource() { |
| int length = this.currentPosition - this.startPosition; |
| char[] tokenSource = new char[length]; |
| System.arraycopy(this.source, this.startPosition, tokenSource, 0, length); |
| return tokenSource; |
| } |
| |
| public final char[] getRawTokenSourceEnd() { |
| int length = this.eofPosition - this.currentPosition - 1; |
| char[] sourceEnd = new char[length]; |
| System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length); |
| return sourceEnd; |
| } |
| |
| public int getCurrentTokenStartPosition(){ |
| return this.startPosition; |
| } |
| /* |
| * Search the source position corresponding to the end of a given line number |
| * |
| * Line numbers are 1-based, and relative to the scanner initialPosition. |
| * Character positions are 0-based. |
| * |
| * In case the given line number is inconsistent, answers -1. |
| */ |
| public final int getLineEnd(int lineNumber) { |
| |
| if (this.lineEnds == null || this.linePtr == -1) |
| return -1; |
| if (lineNumber > this.lineEnds.length+1) |
| return -1; |
| if (lineNumber <= 0) |
| return -1; |
| if (lineNumber == this.lineEnds.length + 1) |
| return this.eofPosition; |
| return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line |
| } |
| |
| public final int[] getLineEnds() { |
| //return a bounded copy of this.lineEnds |
| if (this.linePtr == -1) { |
| return EMPTY_LINE_ENDS; |
| } |
| int[] copy; |
| System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1); |
| return copy; |
| } |
| |
| /** |
| * Search the source position corresponding to the beginning of a given line number |
| * |
| * Line numbers are 1-based, and relative to the scanner initialPosition. |
| * Character positions are 0-based. |
| * |
| * e.g. getLineStart(1) --> 0 indicates that the first line starts at character 0. |
| * |
| * In case the given line number is inconsistent, answers -1. |
| * |
| * @param lineNumber int |
| * @return int |
| */ |
| public final int getLineStart(int lineNumber) { |
| |
| if (this.lineEnds == null || this.linePtr == -1) |
| return -1; |
| if (lineNumber > this.lineEnds.length + 1) |
| return -1; |
| if (lineNumber <= 0) |
| return -1; |
| |
| if (lineNumber == 1) |
| return this.initialPosition; |
| return this.lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line |
| } |
| public final int getNextChar() { |
| try { |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| this.unicodeAsBackSlash = false; |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| return this.currentCharacter; |
| } catch (IndexOutOfBoundsException e) { |
| return -1; |
| } catch(InvalidInputException e) { |
| return -1; |
| } |
| } |
| public final boolean getNextChar(char testedChar) { |
| //BOOLEAN |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| //Both previous lines are true if the currentCharacter is == to the testedChar |
| //On false, no side effect has occured. |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| |
| if (this.currentPosition >= this.source.length) { // handle the obvious case upfront |
| this.unicodeAsBackSlash = false; |
| return false; |
| } |
| |
| int temp = this.currentPosition; |
| try { |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| if (this.currentCharacter != testedChar) { |
| this.currentPosition = temp; |
| this.withoutUnicodePtr--; |
| return false; |
| } |
| return true; |
| } //-------------end unicode traitement-------------- |
| else { |
| if (this.currentCharacter != testedChar) { |
| this.currentPosition = temp; |
| return false; |
| } |
| this.unicodeAsBackSlash = false; |
| if (this.withoutUnicodePtr != 0) |
| unicodeStore(); |
| return true; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.unicodeAsBackSlash = false; |
| this.currentPosition = temp; |
| return false; |
| } catch(InvalidInputException e) { |
| this.unicodeAsBackSlash = false; |
| this.currentPosition = temp; |
| return false; |
| } |
| } |
| public final int getNextChar(char testedChar1, char testedChar2) { |
| //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others |
| //test can be done with (x==0) for the first and (x>0) for the second |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| //Both previous lines are true if the currentCharacter is == to the testedChar1/2 |
| //On false, no side effect has occured. |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| if (this.currentPosition >= this.source.length) // handle the obvious case upfront |
| return -1; |
| |
| int temp = this.currentPosition; |
| try { |
| int result; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| if (this.currentCharacter == testedChar1) { |
| result = 0; |
| } else if (this.currentCharacter == testedChar2) { |
| result = 1; |
| } else { |
| this.currentPosition = temp; |
| this.withoutUnicodePtr--; |
| result = -1; |
| } |
| return result; |
| } else { |
| if (this.currentCharacter == testedChar1) { |
| result = 0; |
| } else if (this.currentCharacter == testedChar2) { |
| result = 1; |
| } else { |
| this.currentPosition = temp; |
| return -1; |
| } |
| |
| if (this.withoutUnicodePtr != 0) |
| unicodeStore(); |
| return result; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition = temp; |
| return -1; |
| } catch(InvalidInputException e) { |
| this.currentPosition = temp; |
| return -1; |
| } |
| } |
| public final boolean getNextCharAsDigit() throws InvalidInputException { |
| //BOOLEAN |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| //Both previous lines are true if the currentCharacter is a digit |
| //On false, no side effect has occured. |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| if (this.currentPosition >= this.source.length) // handle the obvious case upfront |
| return false; |
| |
| int temp = this.currentPosition; |
| try { |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| if (!isDigit(this.currentCharacter)) { |
| this.currentPosition = temp; |
| this.withoutUnicodePtr--; |
| return false; |
| } |
| return true; |
| } else { |
| if (!isDigit(this.currentCharacter)) { |
| this.currentPosition = temp; |
| return false; |
| } |
| if (this.withoutUnicodePtr != 0) |
| unicodeStore(); |
| return true; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition = temp; |
| return false; |
| } catch(InvalidInputException e) { |
| this.currentPosition = temp; |
| return false; |
| } |
| } |
| public final boolean getNextCharAsDigit(int radix) { |
| //BOOLEAN |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| //Both previous lines are true if the currentCharacter is a digit base on radix |
| //On false, no side effect has occured. |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| if (this.currentPosition >= this.source.length) // handle the obvious case upfront |
| return false; |
| |
| int temp = this.currentPosition; |
| try { |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| if (Character.digit(this.currentCharacter, radix) == -1) { |
| this.currentPosition = temp; |
| this.withoutUnicodePtr--; |
| return false; |
| } |
| return true; |
| } else { |
| if (Character.digit(this.currentCharacter, radix) == -1) { |
| this.currentPosition = temp; |
| return false; |
| } |
| if (this.withoutUnicodePtr != 0) |
| unicodeStore(); |
| return true; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition = temp; |
| return false; |
| } catch(InvalidInputException e) { |
| this.currentPosition = temp; |
| return false; |
| } |
| } |
| public boolean getNextCharAsJavaIdentifierPart() { |
| //BOOLEAN |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| //Both previous lines are true if the currentCharacter is a JavaIdentifierPart |
| //On false, no side effect has occured. |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| int pos; |
| if ((pos = this.currentPosition) >= this.source.length) // handle the obvious case upfront |
| return false; |
| |
| int temp2 = this.withoutUnicodePtr; |
| try { |
| boolean unicode = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| unicode = true; |
| } |
| char c = this.currentCharacter; |
| boolean isJavaIdentifierPart = false; |
| if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { |
| if (this.complianceLevel < ClassFileConstants.JDK1_5) { |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } |
| // Unicode 4 detection |
| char low = (char) getNextChar(); |
| if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { |
| // illegal low surrogate |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } |
| isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(c, low); |
| } |
| else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } else { |
| isJavaIdentifierPart = Character.isJavaIdentifierPart(c); |
| } |
| if (unicode) { |
| if (!isJavaIdentifierPart) { |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } |
| return true; |
| } else { |
| if (!isJavaIdentifierPart) { |
| this.currentPosition = pos; |
| return false; |
| } |
| |
| if (this.withoutUnicodePtr != 0) |
| unicodeStore(); |
| return true; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } catch(InvalidInputException e) { |
| this.currentPosition = pos; |
| this.withoutUnicodePtr = temp2; |
| return false; |
| } |
| } |
| public int getNextToken() throws InvalidInputException { |
| this.wasAcr = false; |
| if (this.diet) { |
| jumpOverMethodBody(); |
| this.diet = false; |
| return this.currentPosition > this.source.length ? TokenNameEOF : TokenNameRBRACE; |
| } |
| int whiteStart = 0; |
| try { |
| while (true) { //loop for jumping over comments |
| this.withoutUnicodePtr = 0; |
| //start with a new token (even comment written with unicode ) |
| |
| // ---------Consume white space and handles startPosition--------- |
| whiteStart = this.currentPosition; |
| boolean isWhiteSpace, hasWhiteSpaces = false; |
| int offset; |
| int unicodePtr; |
| boolean checkIfUnicode = false; |
| do { |
| unicodePtr = this.withoutUnicodePtr; |
| offset = this.currentPosition; |
| this.startPosition = this.currentPosition; |
| try { |
| checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u'); |
| } catch(IndexOutOfBoundsException e) { |
| if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { |
| // reposition scanner in case we are interested by spaces as tokens |
| this.currentPosition--; |
| this.startPosition = whiteStart; |
| return TokenNameWHITESPACE; |
| } |
| if (this.currentPosition > this.eofPosition) |
| return TokenNameEOF; |
| } |
| if (checkIfUnicode) { |
| isWhiteSpace = jumpOverUnicodeWhiteSpace(); |
| offset = this.currentPosition - offset; |
| } else { |
| offset = this.currentPosition - offset; |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| checkNonExternalizedString(); |
| if (this.recordLineSeparator) { |
| pushLineSeparator(); |
| } else { |
| this.currentLine = null; |
| } |
| } |
| // inline version of: |
| //isWhiteSpace = |
| // (this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter); |
| switch (this.currentCharacter) { |
| case 10 : /* \ u000a: LINE FEED */ |
| case 12 : /* \ u000c: FORM FEED */ |
| case 13 : /* \ u000d: CARRIAGE RETURN */ |
| case 32 : /* \ u0020: SPACE */ |
| case 9 : /* \ u0009: HORIZONTAL TABULATION */ |
| isWhiteSpace = true; |
| break; |
| default : |
| isWhiteSpace = false; |
| } |
| } |
| if (isWhiteSpace) { |
| hasWhiteSpaces = true; |
| } |
| } while (isWhiteSpace); |
| if (hasWhiteSpaces) { |
| if (this.tokenizeWhiteSpace) { |
| // reposition scanner in case we are interested by spaces as tokens |
| this.currentPosition-=offset; |
| this.startPosition = whiteStart; |
| if (checkIfUnicode) { |
| this.withoutUnicodePtr = unicodePtr; |
| } |
| return TokenNameWHITESPACE; |
| } else if (checkIfUnicode) { |
| this.withoutUnicodePtr = 0; |
| unicodeStore(); |
| } else { |
| this.withoutUnicodePtr = 0; |
| } |
| } |
| //little trick to get out in the middle of a source compuation |
| if (this.currentPosition > this.eofPosition) |
| return TokenNameEOF; |
| |
| // ---------Identify the next token------------- |
| |
| switch (this.currentCharacter) { |
| case '@' : |
| /* if (this.sourceLevel >= ClassFileConstants.JDK1_5) { |
| return TokenNameAT; |
| } else { |
| return TokenNameERROR; |
| }*/ |
| return TokenNameAT; |
| case '(' : |
| return TokenNameLPAREN; |
| case ')' : |
| return TokenNameRPAREN; |
| case '{' : |
| return TokenNameLBRACE; |
| case '}' : |
| return TokenNameRBRACE; |
| case '[' : |
| return TokenNameLBRACKET; |
| case ']' : |
| return TokenNameRBRACKET; |
| case ';' : |
| return TokenNameSEMICOLON; |
| case ',' : |
| return TokenNameCOMMA; |
| case '.' : |
| if (getNextCharAsDigit()) { |
| return scanNumber(true); |
| } |
| /* if (this.sourceLevel >= ClassFileConstants.JDK1_5) { |
| int temp = this.currentPosition; |
| if (getNextChar('.')) { |
| if (getNextChar('.')) { |
| return TokenNameELLIPSIS; |
| } else { |
| this.currentPosition = temp; |
| return TokenNameDOT; |
| } |
| } else { |
| this.currentPosition = temp; |
| return TokenNameDOT; |
| } |
| } else { |
| return TokenNameDOT; |
| }*/ |
| int temp = this.currentPosition; |
| if (getNextChar('.')) { |
| if (getNextChar('.')) { |
| return TokenNameELLIPSIS; |
| } else { |
| this.currentPosition = temp; |
| return TokenNameDOT; |
| } |
| } else { |
| this.currentPosition = temp; |
| return TokenNameDOT; |
| } |
| case '+' : |
| { |
| int test; |
| if ((test = getNextChar('+', '=')) == 0) |
| return TokenNamePLUS_PLUS; |
| if (test > 0) |
| return TokenNamePLUS_EQUAL; |
| return TokenNamePLUS; |
| } |
| case '-' : |
| { |
| int test; |
| if ((test = getNextChar('-', '=')) == 0) |
| return TokenNameMINUS_MINUS; |
| if (test > 0) |
| return TokenNameMINUS_EQUAL; |
| return TokenNameMINUS; |
| } |
| case '~' : |
| return TokenNameTWIDDLE; |
| case '!' : |
| if (getNextChar('=')) |
| return TokenNameNOT_EQUAL; |
| return TokenNameNOT; |
| case '*' : |
| if (getNextChar('=')) |
| return TokenNameMULTIPLY_EQUAL; |
| return TokenNameMULTIPLY; |
| case '%' : |
| if (getNextChar('=')) |
| return TokenNameREMAINDER_EQUAL; |
| return TokenNameREMAINDER; |
| case '<' : |
| { |
| int test; |
| if ((test = getNextChar('=', '<')) == 0) |
| return TokenNameLESS_EQUAL; |
| if (test > 0) { |
| if (getNextChar('=')) |
| return TokenNameLEFT_SHIFT_EQUAL; |
| return TokenNameLEFT_SHIFT; |
| } |
| return TokenNameLESS; |
| } |
| case '>' : |
| { |
| int test; |
| if (this.returnOnlyGreater) { |
| return TokenNameGREATER; |
| } |
| if ((test = getNextChar('=', '>')) == 0) |
| return TokenNameGREATER_EQUAL; |
| if (test > 0) { |
| if ((test = getNextChar('=', '>')) == 0) |
| return TokenNameRIGHT_SHIFT_EQUAL; |
| if (test > 0) { |
| if (getNextChar('=')) |
| return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL; |
| return TokenNameUNSIGNED_RIGHT_SHIFT; |
| } |
| return TokenNameRIGHT_SHIFT; |
| } |
| return TokenNameGREATER; |
| } |
| case '=' : |
| if (getNextChar('=')) |
| return TokenNameEQUAL_EQUAL; |
| return TokenNameEQUAL; |
| case '&' : |
| { |
| int test; |
| if ((test = getNextChar('&', '=')) == 0) |
| return TokenNameAND_AND; |
| if (test > 0) |
| return TokenNameAND_EQUAL; |
| return TokenNameAND; |
| } |
| case '|' : |
| { |
| int test; |
| if ((test = getNextChar('|', '=')) == 0) |
| return TokenNameOR_OR; |
| if (test > 0) |
| return TokenNameOR_EQUAL; |
| return TokenNameOR; |
| } |
| case '^' : |
| if (getNextChar('=')) |
| return TokenNameXOR_EQUAL; |
| return TokenNameXOR; |
| case '?' : |
| return TokenNameQUESTION; |
| case ':' : |
| return TokenNameCOLON; |
| case '\'' : |
| { |
| int test; |
| if ((test = getNextChar('\n', '\r')) == 0) { |
| throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); |
| } |
| if (test > 0) { |
| // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed |
| for (int lookAhead = 0; lookAhead < 3; lookAhead++) { |
| if (this.currentPosition + lookAhead == this.source.length) |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\n') |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\'') { |
| this.currentPosition += lookAhead + 1; |
| break; |
| } |
| } |
| throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); |
| } |
| } |
| if (getNextChar('\'')) { |
| // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed |
| for (int lookAhead = 0; lookAhead < 3; lookAhead++) { |
| if (this.currentPosition + lookAhead == this.source.length) |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\n') |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\'') { |
| this.currentPosition += lookAhead + 1; |
| break; |
| } |
| } |
| throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); |
| } |
| if (getNextChar('\\')) { |
| if (this.unicodeAsBackSlash) { |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } else { |
| this.currentCharacter = this.source[this.currentPosition++]; |
| } |
| scanEscapeCharacter(); |
| } else { // consume next character |
| this.unicodeAsBackSlash = false; |
| checkIfUnicode = false; |
| try { |
| checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u'); |
| } catch(IndexOutOfBoundsException e) { |
| this.currentPosition--; |
| throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); |
| } |
| if (checkIfUnicode) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } |
| if (getNextChar('\'')) |
| return TokenNameCharacterLiteral; |
| // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed |
| for (int lookAhead = 0; lookAhead < 20; lookAhead++) { |
| if (this.currentPosition + lookAhead == this.source.length) |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\n') |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\'') { |
| this.currentPosition += lookAhead + 1; |
| break; |
| } |
| } |
| throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); |
| case '"' : |
| try { |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| boolean isUnicode = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| while (this.currentCharacter != '"') { |
| /**** \r and \n are not valid in string literals ****/ |
| if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) { |
| // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed |
| if (isUnicode) { |
| int start = this.currentPosition; |
| for (int lookAhead = 0; lookAhead < 50; lookAhead++) { |
| if (this.currentPosition >= this.eofPosition) { |
| this.currentPosition = start; |
| break; |
| } |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { |
| isUnicode = true; |
| getNextUnicodeChar(); |
| } else { |
| isUnicode = false; |
| } |
| if (!isUnicode && this.currentCharacter == '\n') { |
| this.currentPosition--; // set current position on new line character |
| break; |
| } |
| if (this.currentCharacter == '\"') { |
| throw new InvalidInputException(INVALID_CHAR_IN_STRING); |
| } |
| } |
| } else { |
| this.currentPosition--; // set current position on new line character |
| } |
| throw new InvalidInputException(INVALID_CHAR_IN_STRING); |
| } |
| if (this.currentCharacter == '\\') { |
| if (this.unicodeAsBackSlash) { |
| this.withoutUnicodePtr--; |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| this.withoutUnicodePtr--; |
| } |
| } else { |
| if (this.withoutUnicodePtr == 0) { |
| unicodeInitializeBuffer(this.currentPosition - this.startPosition); |
| } |
| this.withoutUnicodePtr --; |
| this.currentCharacter = this.source[this.currentPosition++]; |
| } |
| // we need to compute the escape character in a separate buffer |
| scanEscapeCharacter(); |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition--; |
| throw new InvalidInputException(UNTERMINATED_STRING); |
| } catch (InvalidInputException e) { |
| if (e.getMessage().equals(INVALID_ESCAPE)) { |
| // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed |
| for (int lookAhead = 0; lookAhead < 50; lookAhead++) { |
| if (this.currentPosition + lookAhead == this.source.length) |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\n') |
| break; |
| if (this.source[this.currentPosition + lookAhead] == '\"') { |
| this.currentPosition += lookAhead + 1; |
| break; |
| } |
| } |
| |
| } |
| throw e; // rethrow |
| } |
| if (this.checkNonExternalizedStringLiterals){ // check for presence of NLS tags //$NON-NLS-?$ where ? is an int. |
| if (this.currentLine == null) { |
| this.currentLine = new NLSLine(); |
| } |
| this.currentLine.add( |
| new StringLiteral( |
| getCurrentTokenSourceString(), |
| this.startPosition, |
| this.currentPosition - 1)); |
| } |
| return TokenNameStringLiteral; |
| case '/' : |
| { |
| int test; |
| if ((test = getNextChar('/', '*')) == 0) { //line comment |
| this.lastCommentLinePosition = this.currentPosition; |
| try { //get the next char |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } |
| |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| boolean isUnicode = false; |
| while (this.currentCharacter != '\r' && this.currentCharacter != '\n') { |
| this.lastCommentLinePosition = this.currentPosition; |
| //get the next char |
| isUnicode = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| } |
| /* |
| * We need to completely consume the line break |
| */ |
| if (this.currentCharacter == '\r' |
| && this.source.length > this.currentPosition) { |
| if (this.source[this.currentPosition] == '\n') { |
| this.currentPosition++; |
| this.currentCharacter = '\n'; |
| } else if ((this.source[this.currentPosition] == '\\') |
| && (this.source[this.currentPosition + 1] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } |
| } |
| recordComment(TokenNameCOMMENT_LINE); |
| if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| checkNonExternalizedString(); |
| if (this.recordLineSeparator) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } else { |
| this.currentLine = null; |
| } |
| } |
| if (this.tokenizeComments) { |
| return TokenNameCOMMENT_LINE; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition--; |
| recordComment(TokenNameCOMMENT_LINE); |
| if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); |
| if (this.tokenizeComments) { |
| return TokenNameCOMMENT_LINE; |
| } else { |
| this.currentPosition++; |
| } |
| } |
| break; |
| } |
| if (test > 0) { //traditional and javadoc comment |
| try { //get the next char |
| boolean isJavadoc = false, star = false; |
| boolean isUnicode = false; |
| int previous; |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if (this.currentCharacter == '*') { |
| isJavadoc = true; |
| star = true; |
| } |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| checkNonExternalizedString(); |
| if (this.recordLineSeparator) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } else { |
| this.currentLine = null; |
| } |
| } |
| isUnicode = false; |
| previous = this.currentPosition; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| //-------------unicode traitement ------------ |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; //jump over the \\ |
| } |
| // empty comment is not a javadoc /**/ |
| if (this.currentCharacter == '/') { |
| isJavadoc = false; |
| } |
| //loop until end of comment */ |
| int firstTag = 0; |
| while ((this.currentCharacter != '/') || (!star)) { |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| checkNonExternalizedString(); |
| if (this.recordLineSeparator) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } else { |
| this.currentLine = null; |
| } |
| } |
| switch (this.currentCharacter) { |
| case '*': |
| star = true; |
| break; |
| case '@': |
| if (firstTag == 0) { |
| firstTag = previous; |
| } |
| // fall through default case to set star to false |
| default: |
| star = false; |
| } |
| //get next char |
| previous = this.currentPosition; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| //-------------unicode traitement ------------ |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| } |
| int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK; |
| recordComment(token); |
| this.commentTagStarts[this.commentPtr] = firstTag; |
| if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); |
| if (this.tokenizeComments) { |
| /* |
| if (isJavadoc) |
| return TokenNameCOMMENT_JAVADOC; |
| return TokenNameCOMMENT_BLOCK; |
| */ |
| return token; |
| } |
| } catch (IndexOutOfBoundsException e) { |
| this.currentPosition--; |
| throw new InvalidInputException(UNTERMINATED_COMMENT); |
| } |
| break; |
| } |
| if (getNextChar('=')) |
| return TokenNameDIVIDE_EQUAL; |
| return TokenNameDIVIDE; |
| } |
| case '\u001a' : |
| if (atEnd()) |
| return TokenNameEOF; |
| //the atEnd may not be <currentPosition == source.length> if source is only some part of a real (external) stream |
| throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$ |
| |
| default : |
| char c = this.currentCharacter; |
| if (c < MAX_OBVIOUS) { |
| switch (ObviousIdentCharNatures[c]) { |
| case C_LETTER : |
| return scanIdentifierOrKeyword(); |
| case C_DIGIT : |
| return scanNumber(false); |
| } |
| } |
| boolean isJavaIdStart; |
| if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { |
| if (this.complianceLevel < ClassFileConstants.JDK1_5) { |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| // Unicode 4 detection |
| char low = (char) getNextChar(); |
| if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { |
| // illegal low surrogate |
| throw new InvalidInputException(INVALID_LOW_SURROGATE); |
| } |
| isJavaIdStart = ScannerHelper.isJavaIdentifierStart(c, low); |
| } |
| else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { |
| if (this.complianceLevel < ClassFileConstants.JDK1_5) { |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| throw new InvalidInputException(INVALID_HIGH_SURROGATE); |
| } else { |
| isJavaIdStart = Character.isJavaIdentifierStart(c); |
| } |
| if (isJavaIdStart) |
| return scanIdentifierOrKeyword(); |
| if (isDigit(this.currentCharacter)) { |
| return scanNumber(false); |
| } |
| return TokenNameERROR; |
| } |
| } |
| } //-----------------end switch while try-------------------- |
| catch (IndexOutOfBoundsException e) { |
| if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) { |
| // reposition scanner in case we are interested by spaces as tokens |
| this.currentPosition--; |
| this.startPosition = whiteStart; |
| return TokenNameWHITESPACE; |
| } |
| } |
| return TokenNameEOF; |
| } |
| public void getNextUnicodeChar() |
| throws InvalidInputException { |
| //VOID |
| //handle the case of unicode. |
| //when a unicode appears then we must use a buffer that holds char internal values |
| //At the end of this method currentCharacter holds the new visited char |
| //and currentPosition points right next after it |
| |
| //ALL getNextChar.... ARE OPTIMIZED COPIES |
| |
| try { |
| int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6; |
| this.currentPosition++; |
| while (this.source[this.currentPosition] == 'u') { |
| this.currentPosition++; |
| unicodeSize++; |
| } |
| |
| if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 |
| || c1 < 0 |
| || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 |
| || c2 < 0 |
| || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 |
| || c3 < 0 |
| || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 |
| || c4 < 0){ |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); |
| //need the unicode buffer |
| if (this.withoutUnicodePtr == 0) { |
| //buffer all the entries that have been left aside.... |
| unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition); |
| } |
| //fill the buffer with the char |
| unicodeStore(); |
| this.unicodeAsBackSlash = this.currentCharacter == '\\'; |
| } catch (ArrayIndexOutOfBoundsException e) { |
| this.currentPosition--; |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| } |
| |
| public char[] getSource(){ |
| return this.source; |
| } |
| // TODO (philippe) should simply switch on character |
| protected boolean isDigit(char c) throws InvalidInputException { |
| if (Character.isDigit(c)) { |
| switch(c) { |
| case '0' : |
| case '1' : |
| case '2' : |
| case '3' : |
| case '4' : |
| case '5' : |
| case '6' : |
| case '7' : |
| case '8' : |
| case '9' : |
| return true; |
| } |
| throw new InvalidInputException(Scanner.INVALID_DIGIT); |
| } else { |
| return false; |
| } |
| } |
| public final void jumpOverMethodBody() { |
| |
| this.wasAcr = false; |
| int found = 1; |
| try { |
| while (true) { //loop for jumping over comments |
| // ---------Consume white space and handles startPosition--------- |
| boolean isWhiteSpace; |
| do { |
| this.startPosition = this.currentPosition; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| isWhiteSpace = jumpOverUnicodeWhiteSpace(); |
| } else { |
| if (this.recordLineSeparator |
| && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) |
| pushLineSeparator(); |
| isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter); |
| } |
| } while (isWhiteSpace); |
| |
| // -------consume token until } is found--------- |
| NextToken: switch (this.currentCharacter) { |
| case '{' : |
| found++; |
| break NextToken; |
| case '}' : |
| found--; |
| if (found == 0) |
| return; |
| break NextToken; |
| case '\'' : |
| { |
| boolean test; |
| test = getNextChar('\\'); |
| if (test) { |
| try { |
| if (this.unicodeAsBackSlash) { |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } else { |
| this.currentCharacter = this.source[this.currentPosition++]; |
| } |
| scanEscapeCharacter(); |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| } else { |
| try { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| } |
| getNextChar('\''); |
| break NextToken; |
| } |
| case '"' : |
| try { |
| try { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| while (this.currentCharacter != '"') { |
| if (this.currentCharacter == '\r'){ |
| if (this.source[this.currentPosition] == '\n') this.currentPosition++; |
| break NextToken; // the string cannot go further that the line |
| } |
| if (this.currentCharacter == '\n'){ |
| break; // the string cannot go further that the line |
| } |
| if (this.currentCharacter == '\\') { |
| try { |
| if (this.unicodeAsBackSlash) { |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } else { |
| this.currentCharacter = this.source[this.currentPosition++]; |
| } |
| scanEscapeCharacter(); |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| } |
| try { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| } |
| } catch (IndexOutOfBoundsException e) { |
| return; |
| } |
| break NextToken; |
| case '/' : |
| { |
| int test; |
| if ((test = getNextChar('/', '*')) == 0) { //line comment |
| try { |
| this.lastCommentLinePosition = this.currentPosition; |
| //get the next char |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| boolean isUnicode = false; |
| while (this.currentCharacter != '\r' && this.currentCharacter != '\n') { |
| this.lastCommentLinePosition = this.currentPosition; |
| //get the next char |
| isUnicode = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| isUnicode = true; |
| getNextUnicodeChar(); |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| } |
| /* |
| * We need to completely consume the line break |
| */ |
| if (this.currentCharacter == '\r' |
| && this.source.length > this.currentPosition) { |
| if (this.source[this.currentPosition] == '\n') { |
| this.currentPosition++; |
| this.currentCharacter = '\n'; |
| } else if ((this.source[this.currentPosition] == '\\') |
| && (this.source[this.currentPosition + 1] == 'u')) { |
| isUnicode = true; |
| getNextUnicodeChar(); |
| } |
| } |
| recordComment(TokenNameCOMMENT_LINE); |
| if (this.recordLineSeparator |
| && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } |
| } catch (IndexOutOfBoundsException e) { |
| //an eof will then be generated |
| this.currentPosition--; |
| recordComment(TokenNameCOMMENT_LINE); |
| if (!this.tokenizeComments) { |
| this.currentPosition++; |
| } |
| } |
| break NextToken; |
| } |
| if (test > 0) { //traditional and javadoc comment |
| boolean isJavadoc = false; |
| try { //get the next char |
| boolean star = false; |
| int previous; |
| boolean isUnicode = false; |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if (this.currentCharacter == '*') { |
| isJavadoc = true; |
| star = true; |
| } |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| if (this.recordLineSeparator) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } else { |
| this.currentLine = null; |
| } |
| } |
| isUnicode = false; |
| previous = this.currentPosition; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; //jump over the \\ |
| } |
| // empty comment is not a javadoc /**/ |
| if (this.currentCharacter == '/') { |
| isJavadoc = false; |
| } |
| //loop until end of comment */ |
| int firstTag = 0; |
| while ((this.currentCharacter != '/') || (!star)) { |
| if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) { |
| if (this.recordLineSeparator) { |
| if (isUnicode) { |
| pushUnicodeLineSeparator(); |
| } else { |
| pushLineSeparator(); |
| } |
| } else { |
| this.currentLine = null; |
| } |
| } |
| switch (this.currentCharacter) { |
| case '*': |
| star = true; |
| break; |
| case '@': |
| if (firstTag == 0) { |
| firstTag = previous; |
| } |
| // fall through default case to set star to false |
| default: |
| star = false; |
| } |
| //get next char |
| previous = this.currentPosition; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| isUnicode = true; |
| } else { |
| isUnicode = false; |
| } |
| //handle the \\u case manually into comment |
| if (this.currentCharacter == '\\') { |
| if (this.source[this.currentPosition] == '\\') |
| this.currentPosition++; |
| } //jump over the \\ |
| } |
| recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK); |
| this.commentTagStarts[this.commentPtr] = firstTag; |
| } catch (IndexOutOfBoundsException e) { |
| return; |
| } |
| break NextToken; |
| } |
| break NextToken; |
| } |
| |
| default : |
| try { |
| char c = this.currentCharacter; |
| if (c < MAX_OBVIOUS) { |
| switch (ObviousIdentCharNatures[c]) { |
| case C_LETTER : |
| scanIdentifierOrKeyword(); |
| break NextToken; |
| case C_DIGIT : |
| scanNumber(false); |
| break NextToken; |
| } |
| } |
| boolean isJavaIdStart; |
| if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) { |
| if (this.complianceLevel < ClassFileConstants.JDK1_5) { |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| // Unicode 4 detection |
| char low = (char) getNextChar(); |
| if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) { |
| // illegal low surrogate |
| throw new InvalidInputException(INVALID_LOW_SURROGATE); |
| } |
| isJavaIdStart = ScannerHelper.isJavaIdentifierStart(c, low); |
| } |
| else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) { |
| if (this.complianceLevel < ClassFileConstants.JDK1_5) { |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| throw new InvalidInputException(INVALID_HIGH_SURROGATE); |
| } else { |
| isJavaIdStart = Character.isJavaIdentifierStart(c); |
| } |
| if (isJavaIdStart) { |
| scanIdentifierOrKeyword(); |
| break NextToken; |
| } |
| if (isDigit(this.currentCharacter)) { |
| scanNumber(false); |
| break NextToken; |
| } |
| } catch (InvalidInputException ex) { |
| // ignore |
| } |
| } |
| } |
| //-----------------end switch while try-------------------- |
| } catch (IndexOutOfBoundsException e) { |
| // ignore |
| } catch (InvalidInputException e) { |
| // ignore |
| } |
| return; |
| } |
| public final boolean jumpOverUnicodeWhiteSpace() throws InvalidInputException { |
| //BOOLEAN |
| //handle the case of unicode. Jump over the next whiteSpace |
| //making startPosition pointing on the next available char |
| //On false, the currentCharacter is filled up with a potential |
| //correct char |
| |
| try { |
| this.wasAcr = false; |
| getNextUnicodeChar(); |
| return CharOperation.isWhitespace(this.currentCharacter); |
| } catch (IndexOutOfBoundsException e){ |
| this.currentPosition--; |
| throw new InvalidInputException(INVALID_UNICODE_ESCAPE); |
| } |
| } |
| |
| final char[] optimizedCurrentTokenSource1() { |
| //return always the same char[] build only once |
| |
| //optimization at no speed cost of 99.5 % of the singleCharIdentifier |
| char charOne = this.source[this.startPosition]; |
| switch (charOne) { |
| case 'a' : |
| return charArray_a; |
| case 'b' : |
| return charArray_b; |
| case 'c' : |
| return charArray_c; |
| case 'd' : |
| return charArray_d; |
| case 'e' : |
| return charArray_e; |
| case 'f' : |
| return charArray_f; |
| case 'g' : |
| return charArray_g; |
| case 'h' : |
| return charArray_h; |
| case 'i' : |
| return charArray_i; |
| case 'j' : |
| return charArray_j; |
| case 'k' : |
| return charArray_k; |
| case 'l' : |
| return charArray_l; |
| case 'm' : |
| return charArray_m; |
| case 'n' : |
| return charArray_n; |
| case 'o' : |
| return charArray_o; |
| case 'p' : |
| return charArray_p; |
| case 'q' : |
| return charArray_q; |
| case 'r' : |
| return charArray_r; |
| case 's' : |
| return charArray_s; |
| case 't' : |
| return charArray_t; |
| case 'u' : |
| return charArray_u; |
| case 'v' : |
| return charArray_v; |
| case 'w' : |
| return charArray_w; |
| case 'x' : |
| return charArray_x; |
| case 'y' : |
| return charArray_y; |
| case 'z' : |
| return charArray_z; |
| default : |
| return new char[] {charOne}; |
| } |
| } |
| final char[] optimizedCurrentTokenSource2() { |
| //try to return the same char[] build only once |
| |
| char[] src = this.source; |
| int start = this.startPosition; |
| char c0 , c1; |
| int hash = (((c0=src[start]) << 6) + (c1=src[start+1])) % TableSize; |
| char[][] table = this.charArray_length[0][hash]; |
| int i = newEntry2; |
| while (++i < InternalTableSize) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) && (c1 == charArray[1])) |
| return charArray; |
| } |
| //---------other side--------- |
| i = -1; |
| int max = newEntry2; |
| while (++i <= max) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) && (c1 == charArray[1])) |
| return charArray; |
| } |
| //--------add the entry------- |
| if (++max >= InternalTableSize) max = 0; |
| char[] r; |
| System.arraycopy(src, start, r= new char[2], 0, 2); |
| //newIdentCount++; |
| return table[newEntry2 = max] = r; //(r = new char[] {c0, c1}); |
| } |
| final char[] optimizedCurrentTokenSource3() { |
| //try to return the same char[] build only once |
| |
| char[] src = this.source; |
| int start = this.startPosition; |
| char c0, c1=src[start+1], c2; |
| int hash = (((c0=src[start])<< 6) + (c2=src[start+2])) % TableSize; |
| // int hash = ((c0 << 12) + (c1<< 6) + c2) % TableSize; |
| char[][] table = this.charArray_length[1][hash]; |
| int i = newEntry3; |
| while (++i < InternalTableSize) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])) |
| return charArray; |
| } |
| //---------other side--------- |
| i = -1; |
| int max = newEntry3; |
| while (++i <= max) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2])) |
| return charArray; |
| } |
| //--------add the entry------- |
| if (++max >= InternalTableSize) max = 0; |
| char[] r; |
| System.arraycopy(src, start, r= new char[3], 0, 3); |
| //newIdentCount++; |
| return table[newEntry3 = max] = r; //(r = new char[] {c0, c1, c2}); |
| } |
| final char[] optimizedCurrentTokenSource4() { |
| //try to return the same char[] build only once |
| |
| char[] src = this.source; |
| int start = this.startPosition; |
| char c0, c1 = src[start+1], c2, c3 = src[start+3]; |
| int hash = (((c0=src[start]) << 6) + (c2=src[start+2])) % TableSize; |
| // int hash = (int) (((((long) c0) << 18) + (c1 << 12) + (c2 << 6) + c3) % TableSize); |
| char[][] table = this.charArray_length[2][hash]; |
| int i = newEntry4; |
| while (++i < InternalTableSize) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3])) |
| return charArray; |
| } |
| //---------other side--------- |
| i = -1; |
| int max = newEntry4; |
| while (++i <= max) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3])) |
| return charArray; |
| } |
| //--------add the entry------- |
| if (++max >= InternalTableSize) max = 0; |
| char[] r; |
| System.arraycopy(src, start, r= new char[4], 0, 4); |
| //newIdentCount++; |
| return table[newEntry4 = max] = r; //(r = new char[] {c0, c1, c2, c3}); |
| } |
| final char[] optimizedCurrentTokenSource5() { |
| //try to return the same char[] build only once |
| |
| char[] src = this.source; |
| int start = this.startPosition; |
| char c0, c1 = src[start+1], c2, c3 = src[start+3], c4; |
| int hash = (((c0=src[start]) << 12) +((c2=src[start+2]) << 6) + (c4=src[start+4])) % TableSize; |
| // int hash = (int) (((((long) c0) << 24) + (((long) c1) << 18) + (c2 << 12) + (c3 << 6) + c4) % TableSize); |
| char[][] table = this.charArray_length[3][hash]; |
| int i = newEntry5; |
| while (++i < InternalTableSize) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3]) |
| && (c4 == charArray[4])) |
| return charArray; |
| } |
| //---------other side--------- |
| i = -1; |
| int max = newEntry5; |
| while (++i <= max) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3]) |
| && (c4 == charArray[4])) |
| return charArray; |
| } |
| //--------add the entry------- |
| if (++max >= InternalTableSize) max = 0; |
| char[] r; |
| System.arraycopy(src, start, r= new char[5], 0, 5); |
| //newIdentCount++; |
| return table[newEntry5 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4}); |
| } |
| final char[] optimizedCurrentTokenSource6() { |
| //try to return the same char[] build only once |
| |
| char[] src = this.source; |
| int start = this.startPosition; |
| char c0, c1 = src[start+1], c2, c3 = src[start+3], c4, c5 = src[start+5]; |
| int hash = (((c0=src[start]) << 12) +((c2=src[start+2]) << 6) + (c4=src[start+4])) % TableSize; |
| // int hash = (int)(((((long) c0) << 32) + (((long) c1) << 24) + (((long) c2) << 18) + (c3 << 12) + (c4 << 6) + c5) % TableSize); |
| char[][] table = this.charArray_length[4][hash]; |
| int i = newEntry6; |
| while (++i < InternalTableSize) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3]) |
| && (c4 == charArray[4]) |
| && (c5 == charArray[5])) |
| return charArray; |
| } |
| //---------other side--------- |
| i = -1; |
| int max = newEntry6; |
| while (++i <= max) { |
| char[] charArray = table[i]; |
| if ((c0 == charArray[0]) |
| && (c1 == charArray[1]) |
| && (c2 == charArray[2]) |
| && (c3 == charArray[3]) |
| && (c4 == charArray[4]) |
| && (c5 == charArray[5])) |
| return charArray; |
| } |
| //--------add the entry------- |
| if (++max >= InternalTableSize) max = 0; |
| char[] r; |
| System.arraycopy(src, start, r= new char[6], 0, 6); |
| //newIdentCount++; |
| return table[newEntry6 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4, c5}); |
| } |
| |
| protected void parseTags(NLSLine line) { |
| String s = new String(getCurrentTokenSource()); |
| int pos = s.indexOf(TAG_PREFIX); |
| int lineLength = line.size(); |
| while (pos != -1) { |
| int start = pos + TAG_PREFIX_LENGTH; |
| int end = s.indexOf(TAG_POSTFIX, start); |
| if (end != -1) { |
| String index = s.substring(start, end); |
| int i = 0; |
| try { |
| i = Integer.parseInt(index) - 1; // Tags are one based not zero based. |
| } catch (NumberFormatException e) { |
| i = -1; // we don't want to consider this as a valid NLS tag |
| } |
| if (line.exists(i)) { |
| line.set(i, null); |
| } |
| } |
| pos = s.indexOf(TAG_PREFIX, start); |
| } |
| |
| this.nonNLSStrings = new StringLiteral[lineLength]; |
| int nonNLSCounter = 0; |
| for (Iterator iterator = line.iterator(); iterator.hasNext(); ) { |
| StringLiteral literal = (StringLiteral) iterator.next(); |
| if (literal != null) { |
| this.nonNLSStrings[nonNLSCounter++] = literal; |
| } |
| } |
| if (nonNLSCounter == 0) { |
| this.nonNLSStrings = null; |
| this.currentLine = null; |
| return; |
| } |
| this.wasNonExternalizedStringLiteral = true; |
| if (nonNLSCounter != lineLength) { |
| System.arraycopy(this.nonNLSStrings, 0, (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0, nonNLSCounter); |
| } |
| this.currentLine = null; |
| } |
| |
| public final void pushLineSeparator() { |
| //see comment on isLineDelimiter(char) for the use of '\n' and '\r' |
| final int INCREMENT = 250; |
| |
| if (this.checkNonExternalizedStringLiterals) { |
| // reinitialize the current line for non externalize strings purpose |
| this.currentLine = null; |
| } |
| //currentCharacter is at position currentPosition-1 |
| |
| // cr 000D |
| if (this.currentCharacter == '\r') { |
| int separatorPos = this.currentPosition - 1; |
| //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ? |
| if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return; |
| //System.out.println("CR-" + separatorPos); |
| int length = this.lineEnds.length; |
| if (++this.linePtr >= length) |
| System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length); |
| this.lineEnds[this.linePtr] = separatorPos; |
| // look-ahead for merged cr+lf |
| try { |
| if (this.source[this.currentPosition] == '\n') { |
| //System.out.println("look-ahead LF-" + this.currentPosition); |
| this.lineEnds[this.linePtr] = this.currentPosition; |
| this.currentPosition++; |
| this.wasAcr = false; |
| } else { |
| this.wasAcr = true; |
| } |
| } catch(IndexOutOfBoundsException e) { |
| this.wasAcr = true; |
| } |
| } else { |
| // lf 000A |
| if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf |
| if (this.wasAcr && (this.lineEnds[this.linePtr] == (this.currentPosition - 2))) { |
| //System.out.println("merge LF-" + (this.currentPosition - 1)); |
| this.lineEnds[this.linePtr] = this.currentPosition - 1; |
| } else { |
| int separatorPos = this.currentPosition - 1; |
| //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ? |
| if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return; |
| // System.out.println("LF-" + separatorPos); |
| int length = this.lineEnds.length; |
| if (++this.linePtr >= length) |
| System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length); |
| this.lineEnds[this.linePtr] = separatorPos; |
| } |
| this.wasAcr = false; |
| } |
| } |
| } |
| public final void pushUnicodeLineSeparator() { |
| if (this.checkNonExternalizedStringLiterals) { |
| // reinitialize the current line for non externalize strings purpose |
| this.currentLine = null; |
| } |
| |
| // cr 000D |
| if (this.currentCharacter == '\r') { |
| if (this.source[this.currentPosition] == '\n') { |
| this.wasAcr = false; |
| } else { |
| this.wasAcr = true; |
| } |
| } else { |
| // lf 000A |
| if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf |
| this.wasAcr = false; |
| } |
| } |
| } |
| |
| public void recordComment(int token) { |
| // compute position |
| int stopPosition = this.currentPosition; |
| switch (token) { |
| case TokenNameCOMMENT_LINE: |
| stopPosition = -this.lastCommentLinePosition; |
| break; |
| case TokenNameCOMMENT_BLOCK: |
| stopPosition = -this.currentPosition; |
| break; |
| } |
| |
| // a new comment is recorded |
| int length = this.commentStops.length; |
| if (++this.commentPtr >= length) { |
| int newLength = length + COMMENT_ARRAYS_SIZE*10; |
| System.arraycopy(this.commentStops, 0, this.commentStops = new int[newLength], 0, length); |
| System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[newLength], 0, length); |
| System.arraycopy(this.commentTagStarts, 0, this.commentTagStarts = new int[newLength], 0, length); |
| } |
| this.commentStops[this.commentPtr] = stopPosition; |
| this.commentStarts[this.commentPtr] = this.startPosition; |
| } |
| |
| /** |
| * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position. |
| * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>). |
| * |
| * @param begin the given start position |
| * @param end the given end position |
| */ |
| public void resetTo(int begin, int end) { |
| //reset the scanner to a given position where it may rescan again |
| |
| this.diet = false; |
| this.initialPosition = this.startPosition = this.currentPosition = begin; |
| if (this.source != null && this.source.length < end) { |
| this.eofPosition = this.source.length; |
| } else { |
| this.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end; |
| } |
| this.commentPtr = -1; // reset comment stack |
| this.foundTaskCount = 0; |
| |
| // // if resetTo is used with being > than end. |
| // if (begin > this.eofPosition) { |
| // begin = this.eofPosition; |
| // } |
| } |
| |
| public final void scanEscapeCharacter() throws InvalidInputException { |
| // the string with "\\u" is a legal string of two chars \ and u |
| //thus we use a direct access to the source (for regular cases). |
| switch (this.currentCharacter) { |
| case 'b' : |
| this.currentCharacter = '\b'; |
| break; |
| case 't' : |
| this.currentCharacter = '\t'; |
| break; |
| case 'n' : |
| this.currentCharacter = '\n'; |
| break; |
| case 'f' : |
| this.currentCharacter = '\f'; |
| break; |
| case 'r' : |
| this.currentCharacter = '\r'; |
| break; |
| case '\"' : |
| this.currentCharacter = '\"'; |
| break; |
| case '\'' : |
| this.currentCharacter = '\''; |
| break; |
| case '\\' : |
| this.currentCharacter = '\\'; |
| break; |
| default : |
| // -----------octal escape-------------- |
| // OctalDigit |
| // OctalDigit OctalDigit |
| // ZeroToThree OctalDigit OctalDigit |
| |
| int number = Character.getNumericValue(this.currentCharacter); |
| if (number >= 0 && number <= 7) { |
| boolean zeroToThreeNot = number > 3; |
| if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) { |
| int digit = Character.getNumericValue(this.currentCharacter); |
| if (digit >= 0 && digit <= 7) { |
| number = (number * 8) + digit; |
| if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) { |
| if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character |
| this.currentPosition--; |
| } else { |
| digit = Character.getNumericValue(this.currentCharacter); |
| if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit |
| number = (number * 8) + digit; |
| } else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character |
| this.currentPosition--; |
| } |
| } |
| } else { // has read \OctalDigit NonDigit--> ignore last character |
| this.currentPosition--; |
| } |
| } else { // has read \OctalDigit NonOctalDigit--> ignore last character |
| this.currentPosition--; |
| } |
| } else { // has read \OctalDigit --> ignore last character |
| this.currentPosition--; |
| } |
| if (number > 255) |
| throw new InvalidInputException(INVALID_ESCAPE); |
| this.currentCharacter = (char) number; |
| } else |
| throw new InvalidInputException(INVALID_ESCAPE); |
| } |
| } |
| public int scanIdentifierOrKeyword() { |
| //test keywords |
| |
| //first dispatch on the first char. |
| //then the length. If there are several |
| //keywors with the same length AND the same first char, then do another |
| //dispatch on the second char |
| this.useAssertAsAnIndentifier = false; |
| this.useEnumAsAnIndentifier = false; |
| |
| char[] src = this.source; |
| identLoop: { |
| int pos, srcLength = this.source.length; |
| while (true) { |
| if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront |
| break identLoop; |
| char c = src[pos]; |
| if (c < MAX_OBVIOUS) { |
| switch (ObviousIdentCharNatures[c]) { |
| case C_LETTER : |
| case C_DIGIT : |
| if (this.withoutUnicodePtr != 0) { |
| this.currentCharacter = c; |
| unicodeStore(); |
| } |
| this.currentPosition++; |
| break; |
| |
| case C_SEPARATOR : |
| case C_SPACE : |
| this.currentCharacter = c; |
| break identLoop; |
| |
| default: |
| //System.out.println("slow<=128: "+ c); |
| while (getNextCharAsJavaIdentifierPart()){/*empty*/} |
| break identLoop; |
| } |
| } else { |
| //System.out.println("slow>>128: "+ c); |
| while (getNextCharAsJavaIdentifierPart()){/*empty*/} |
| break identLoop; |
| } |
| } |
| } |
| |
| int index, length; |
| char[] data; |
| if (this.withoutUnicodePtr == 0) |
| |
| //quick test on length == 1 but not on length > 12 while most identifier |
| //have a length which is <= 12...but there are lots of identifier with |
| //only one char.... |
| |
| { |
| if ((length = this.currentPosition - this.startPosition) == 1) |
| return TokenNameIdentifier; |
| data = this.source; |
| index = this.startPosition; |
| } else { |
| if ((length = this.withoutUnicodePtr) == 1) |
| return TokenNameIdentifier; |
| data = this.withoutUnicodeBuffer; |
| index = 1; |
| } |
| |
| |
| switch (data[index]) { |
| |
| case 'a' : |
| switch(length) { |
| case 8: //abstract |
| if ((data[++index] == 'b') |
| && (data[++index] == 's') |
| && (data[++index] == 't') |
| && (data[++index] == 'r') |
| && (data[++index] == 'a') |
| && (data[++index] == 'c') |
| && (data[++index] == 't')) { |
| return TokenNameabstract; |
| } else { |
| return TokenNameIdentifier; |
| } |
| case 6: // assert |
| if ((data[++index] == 's') |
| && (data[++index] == 's') |
| && (data[++index] == 'e') |
| && (data[++index] == 'r') |
| && (data[++index] == 't')) { |
| if (this.sourceLevel >= ClassFileConstants.JDK1_4) { |
| this.containsAssertKeyword = true; |
| return TokenNameassert; |
| } else { |
| this.useAssertAsAnIndentifier = true; |
| return TokenNameIdentifier; |
| } |
| } else { |
| return TokenNameIdentifier; |
| } |
| default: |
| return TokenNameIdentifier; |
| } |
| case 'b' : //boolean break byte |
| switch (length) { |
| case 4 : |
| if ((data[++index] == 'y') && (data[++index] == 't') && (data[++index] == 'e')) |
| return TokenNamebyte; |
| else |
| return TokenNameIdentifier; |
| case 5 : |
| if ((data[++index] == 'r') |
| && (data[++index] == 'e') |
| && (data[++index] == 'a') |
| && (data[++index] == 'k')) |
| return TokenNamebreak; |
| else |
| return TokenNameIdentifier; |
| case 7 : |
| if ((data[++index] == 'o') |
| && (data[++index] == 'o') |
| && (data[++index] == 'l') |
| && (data[++index] == 'e') |
| && (data[++index] == 'a') |
| && (data[++index] == 'n')) |
| return TokenNameboolean; |
| else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'c' : //case char catch const class continue |
| switch (length) { |
| case 4 : |
| if (data[++index] == 'a') |
| if ((data[++index] == 's') && (data[++index] == 'e')) |
| return TokenNamecase; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'h') && (data[++index] == 'a') && (data[++index] == 'r')) |
| return TokenNamechar; |
| else |
| return TokenNameIdentifier; |
| case 5 : |
| if (data[++index] == 'a') |
| if ((data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h')) |
| return TokenNamecatch; |
| else |
| return TokenNameIdentifier; |
| else |
| if (data[index] == 'l') |
| if ((data[++index] == 'a') |
| && (data[++index] == 's') |
| && (data[++index] == 's')) |
| return TokenNameclass; |
| else |
| return TokenNameIdentifier; |
| else if ((data[index] == 'o') |
| && (data[++index] == 'n') |
| && (data[++index] == 's') |
| && (data[++index] == 't')) |
| return TokenNameconst; //const is not used in java ??????? |
| else |
| return TokenNameIdentifier; |
| case 8 : |
| if ((data[++index] == 'o') |
| && (data[++index] == 'n') |
| && (data[++index] == 't') |
| && (data[++index] == 'i') |
| && (data[++index] == 'n') |
| && (data[++index] == 'u') |
| && (data[++index] == 'e')) |
| return TokenNamecontinue; |
| else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'd' : //default do double |
| switch (length) { |
| case 2 : |
| if ((data[++index] == 'o')) |
| return TokenNamedo; |
| else |
| return TokenNameIdentifier; |
| case 6 : |
| if ((data[++index] == 'o') |
| && (data[++index] == 'u') |
| && (data[++index] == 'b') |
| && (data[++index] == 'l') |
| && (data[++index] == 'e')) |
| return TokenNamedouble; |
| else |
| return TokenNameIdentifier; |
| case 7 : |
| if ((data[++index] == 'e') |
| && (data[++index] == 'f') |
| && (data[++index] == 'a') |
| && (data[++index] == 'u') |
| && (data[++index] == 'l') |
| && (data[++index] == 't')) |
| return TokenNamedefault; |
| else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| case 'e' : //else extends |
| switch (length) { |
| case 4 : |
| if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e')) |
| return TokenNameelse; |
| else if ((data[index] == 'n') |
| && (data[++index] == 'u') |
| && (data[++index] == 'm')) { |
| if (this.sourceLevel >= ClassFileConstants.JDK1_5) { |
| return TokenNameenum; |
| } else { |
| this.useEnumAsAnIndentifier = true; |
| return TokenNameIdentifier; |
| } |
| } else { |
| return TokenNameIdentifier; |
| } |
| case 7 : |
| if ((data[++index] == 'x') |
| && (data[++index] == 't') |
| && (data[++index] == 'e') |
| && (data[++index] == 'n') |
| && (data[++index] == 'd') |
| && (data[++index] == 's')) |
| return TokenNameextends; |
| else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'f' : //final finally float for false |
| switch (length) { |
| case 3 : |
| if ((data[++index] == 'o') && (data[++index] == 'r')) |
| return TokenNamefor; |
| else |
| return TokenNameIdentifier; |
| case 5 : |
| if (data[++index] == 'i') |
| if ((data[++index] == 'n') |
| && (data[++index] == 'a') |
| && (data[++index] == 'l')) { |
| return TokenNamefinal; |
| } else |
| return TokenNameIdentifier; |
| else |
| if (data[index] == 'l') |
| if ((data[++index] == 'o') |
| && (data[++index] == 'a') |
| && (data[++index] == 't')) |
| return TokenNamefloat; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'a') |
| && (data[++index] == 'l') |
| && (data[++index] == 's') |
| && (data[++index] == 'e')) |
| return TokenNamefalse; |
| else |
| return TokenNameIdentifier; |
| case 7 : |
| if ((data[++index] == 'i') |
| && (data[++index] == 'n') |
| && (data[++index] == 'a') |
| && (data[++index] == 'l') |
| && (data[++index] == 'l') |
| && (data[++index] == 'y')) |
| return TokenNamefinally; |
| else |
| return TokenNameIdentifier; |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| case 'g' : //goto |
| if (length == 4) { |
| if ((data[++index] == 'o') |
| && (data[++index] == 't') |
| && (data[++index] == 'o')) { |
| return TokenNamegoto; |
| } |
| } //no goto in java are allowed, so why java removes this keyword ??? |
| return TokenNameIdentifier; |
| |
| case 'i' : //if implements import instanceof int interface |
| switch (length) { |
| case 2 : |
| if (data[++index] == 'f') |
| return TokenNameif; |
| else |
| return TokenNameIdentifier; |
| case 3 : |
| if ((data[++index] == 'n') && (data[++index] == 't')) |
| return TokenNameint; |
| else |
| return TokenNameIdentifier; |
| case 6 : |
| if ((data[++index] == 'm') |
| && (data[++index] == 'p') |
| && (data[++index] == 'o') |
| && (data[++index] == 'r') |
| && (data[++index] == 't')) |
| return TokenNameimport; |
| else |
| return TokenNameIdentifier; |
| case 9 : |
| if ((data[++index] == 'n') |
| && (data[++index] == 't') |
| && (data[++index] == 'e') |
| && (data[++index] == 'r') |
| && (data[++index] == 'f') |
| && (data[++index] == 'a') |
| && (data[++index] == 'c') |
| && (data[++index] == 'e')) |
| return TokenNameinterface; |
| else |
| return TokenNameIdentifier; |
| case 10 : |
| if (data[++index] == 'm') |
| if ((data[++index] == 'p') |
| && (data[++index] == 'l') |
| && (data[++index] == 'e') |
| && (data[++index] == 'm') |
| && (data[++index] == 'e') |
| && (data[++index] == 'n') |
| && (data[++index] == 't') |
| && (data[++index] == 's')) |
| return TokenNameimplements; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'n') |
| && (data[++index] == 's') |
| && (data[++index] == 't') |
| && (data[++index] == 'a') |
| && (data[++index] == 'n') |
| && (data[++index] == 'c') |
| && (data[++index] == 'e') |
| && (data[++index] == 'o') |
| && (data[++index] == 'f')) |
| return TokenNameinstanceof; |
| else |
| return TokenNameIdentifier; |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'l' : //long |
| if (length == 4) { |
| if ((data[++index] == 'o') |
| && (data[++index] == 'n') |
| && (data[++index] == 'g')) { |
| return TokenNamelong; |
| } |
| } |
| return TokenNameIdentifier; |
| |
| case 'n' : //native new null |
| switch (length) { |
| case 3 : |
| if ((data[++index] == 'e') && (data[++index] == 'w')) |
| return TokenNamenew; |
| else |
| return TokenNameIdentifier; |
| case 4 : |
| if ((data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 'l')) |
| return TokenNamenull; |
| else |
| return TokenNameIdentifier; |
| case 6 : |
| if ((data[++index] == 'a') |
| && (data[++index] == 't') |
| && (data[++index] == 'i') |
| && (data[++index] == 'v') |
| && (data[++index] == 'e')) { |
| return TokenNamenative; |
| } else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'p' : //package private protected public |
| switch (length) { |
| case 6 : |
| if ((data[++index] == 'u') |
| && (data[++index] == 'b') |
| && (data[++index] == 'l') |
| && (data[++index] == 'i') |
| && (data[++index] == 'c')) { |
| return TokenNamepublic; |
| } else |
| return TokenNameIdentifier; |
| case 7 : |
| if (data[++index] == 'a') |
| if ((data[++index] == 'c') |
| && (data[++index] == 'k') |
| && (data[++index] == 'a') |
| && (data[++index] == 'g') |
| && (data[++index] == 'e')) |
| return TokenNamepackage; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'r') |
| && (data[++index] == 'i') |
| && (data[++index] == 'v') |
| && (data[++index] == 'a') |
| && (data[++index] == 't') |
| && (data[++index] == 'e')) { |
| return TokenNameprivate; |
| } else |
| return TokenNameIdentifier; |
| case 9 : |
| if ((data[++index] == 'r') |
| && (data[++index] == 'o') |
| && (data[++index] == 't') |
| && (data[++index] == 'e') |
| && (data[++index] == 'c') |
| && (data[++index] == 't') |
| && (data[++index] == 'e') |
| && (data[++index] == 'd')) { |
| return TokenNameprotected; |
| } else |
| return TokenNameIdentifier; |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'r' : //return |
| if (length == 6) { |
| if ((data[++index] == 'e') |
| && (data[++index] == 't') |
| && (data[++index] == 'u') |
| && (data[++index] == 'r') |
| && (data[++index] == 'n')) { |
| return TokenNamereturn; |
| } |
| } |
| return TokenNameIdentifier; |
| |
| case 's' : //short static super switch synchronized strictfp |
| switch (length) { |
| case 5 : |
| if (data[++index] == 'h') |
| if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't')) |
| return TokenNameshort; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'u') |
| && (data[++index] == 'p') |
| && (data[++index] == 'e') |
| && (data[++index] == 'r')) |
| return TokenNamesuper; |
| else |
| return TokenNameIdentifier; |
| |
| case 6 : |
| if (data[++index] == 't') |
| if ((data[++index] == 'a') |
| && (data[++index] == 't') |
| && (data[++index] == 'i') |
| && (data[++index] == 'c')) { |
| return TokenNamestatic; |
| } else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'w') |
| && (data[++index] == 'i') |
| && (data[++index] == 't') |
| && (data[++index] == 'c') |
| && (data[++index] == 'h')) |
| return TokenNameswitch; |
| else |
| return TokenNameIdentifier; |
| case 8 : |
| if ((data[++index] == 't') |
| && (data[++index] == 'r') |
| && (data[++index] == 'i') |
| && (data[++index] == 'c') |
| && (data[++index] == 't') |
| && (data[++index] == 'f') |
| && (data[++index] == 'p')) |
| return TokenNamestrictfp; |
| else |
| return TokenNameIdentifier; |
| case 12 : |
| if ((data[++index] == 'y') |
| && (data[++index] == 'n') |
| && (data[++index] == 'c') |
| && (data[++index] == 'h') |
| && (data[++index] == 'r') |
| && (data[++index] == 'o') |
| && (data[++index] == 'n') |
| && (data[++index] == 'i') |
| && (data[++index] == 'z') |
| && (data[++index] == 'e') |
| && (data[++index] == 'd')) { |
| return TokenNamesynchronized; |
| } else |
| return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 't' : //try throw throws transient this true |
| switch (length) { |
| case 3 : |
| if ((data[++index] == 'r') && (data[++index] == 'y')) |
| return TokenNametry; |
| else |
| return TokenNameIdentifier; |
| case 4 : |
| if (data[++index] == 'h') |
| if ((data[++index] == 'i') && (data[++index] == 's')) |
| return TokenNamethis; |
| else |
| return TokenNameIdentifier; |
| else |
| if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e')) |
| return TokenNametrue; |
| else |
| return TokenNameIdentifier; |
| case 5 : |
| if ((data[++index] == 'h') |
| && (data[++index] == 'r') |
| && (data[++index] == 'o') |
| && (data[++index] == 'w')) |
| return TokenNamethrow; |
| else |
| return TokenNameIdentifier; |
| case 6 : |
| if ((data[++index] == 'h') |
| && (data[++index] == 'r') |
| && (data[++index] == 'o') |
| && (data[++index] == 'w') |
| && (data[++index] == 's')) |
| return TokenNamethrows; |
| else |
| return TokenNameIdentifier; |
| case 9 : |
| if ((data[++index] == 'r') |
| && (data[++index] == 'a') |
| && (data[++index] == 'n') |
| && (data[++index] == 's') |
| && (data[++index] == 'i') |
| && (data[++index] == 'e') |
| && (data[++index] == 'n') |
| && (data[++index] == 't')) { |
| return TokenNametransient; |
| } else |
| return TokenNameIdentifier; |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'v' : //void volatile |
| switch (length) { |
| case 4 : |
| if ((data[++index] == 'o') && (data[++index] == 'i') && (data[++index] == 'd')) |
| return TokenNamevoid; |
| else |
| return TokenNameIdentifier; |
| case 8 : |
| if ((data[++index] == 'o') |
| && (data[++index] == 'l') |
| && (data[++index] == 'a') |
| && (data[++index] == 't') |
| && (data[++index] == 'i') |
| && (data[++index] == 'l') |
| && (data[++index] == 'e')) { |
| return TokenNamevolatile; |
| } else |
| return TokenNameIdentifier; |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| case 'w' : //while widefp |
| switch (length) { |
| case 5 : |
| if ((data[++index] == 'h') |
| && (data[++index] == 'i') |
| && (data[++index] == 'l') |
| && (data[++index] == 'e')) |
| return TokenNamewhile; |
| else |
| return TokenNameIdentifier; |
| //case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&& (data[++index]=='p')) |
| //return TokenNamewidefp ; |
| //else |
| //return TokenNameIdentifier; |
| default : |
| return TokenNameIdentifier; |
| } |
| |
| default : |
| return TokenNameIdentifier; |
| } |
| } |
| |
| |
| public int scanNumber(boolean dotPrefix) throws InvalidInputException { |
| |
| //when entering this method the currentCharacter is the first |
| //digit of the number. It may be preceeded by a '.' when |
| //dotPrefix is true |
| |
| boolean floating = dotPrefix; |
| if ((!dotPrefix) && (this.currentCharacter == '0')) { |
| if (getNextChar('x', 'X') >= 0) { //----------hexa----------------- |
| int start = this.currentPosition; |
| while (getNextCharAsDigit(16)){/*empty*/} |
| int end = this.currentPosition; |
| if (getNextChar('l', 'L') >= 0) { |
| if (end == start) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| return TokenNameLongLiteral; |
| } else if (getNextChar('.')) { |
| if (this.sourceLevel < ClassFileConstants.JDK1_5) { |
| if (end == start) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| this.currentPosition = end; |
| return TokenNameIntegerLiteral; |
| } |
| // hexadecimal floating point literal |
| // read decimal part |
| boolean hasNoDigitsBeforeDot = end == start; |
| start = this.currentPosition; |
| while (getNextCharAsDigit(16)){/*empty*/} |
| end = this.currentPosition; |
| if (hasNoDigitsBeforeDot && end == start) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| |
| if (getNextChar('p', 'P') >= 0) { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if ((this.currentCharacter == '-') |
| || (this.currentCharacter == '+')) { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } |
| if (!isDigit(this.currentCharacter)) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| while (getNextCharAsDigit()){/*empty*/} |
| if (getNextChar('f', 'F') >= 0) { |
| return TokenNameFloatingPointLiteral; |
| } |
| if (getNextChar('d', 'D') >= 0) { |
| return TokenNameDoubleLiteral; |
| } |
| if (getNextChar('l', 'L') >= 0) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| return TokenNameDoubleLiteral; |
| } else { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| } else if (getNextChar('p', 'P') >= 0) { // consume next character |
| if (this.sourceLevel < ClassFileConstants.JDK1_5) { |
| // if we are in source level < 1.5 we report an integer literal |
| this.currentPosition = end; |
| return TokenNameIntegerLiteral; |
| } |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if ((this.currentCharacter == '-') |
| || (this.currentCharacter == '+')) { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } |
| if (!isDigit(this.currentCharacter)) |
| throw new InvalidInputException(INVALID_FLOAT); |
| while (getNextCharAsDigit()){/*empty*/} |
| if (getNextChar('f', 'F') >= 0) |
| return TokenNameFloatingPointLiteral; |
| if (getNextChar('d', 'D') >= 0) |
| return TokenNameDoubleLiteral; |
| if (getNextChar('l', 'L') >= 0) { |
| throw new InvalidInputException(INVALID_HEXA); |
| } |
| return TokenNameDoubleLiteral; |
| } else { |
| if (end == start) |
| throw new InvalidInputException(INVALID_HEXA); |
| return TokenNameIntegerLiteral; |
| } |
| } |
| |
| //there is x or X in the number |
| //potential octal ! ... some one may write 000099.0 ! thus 00100 < 00078.0 is true !!!!! crazy language |
| if (getNextCharAsDigit()) { //-------------potential octal----------------- |
| while (getNextCharAsDigit()){/*empty*/} |
| |
| if (getNextChar('l', 'L') >= 0) { |
| return TokenNameLongLiteral; |
| } |
| |
| if (getNextChar('f', 'F') >= 0) { |
| return TokenNameFloatingPointLiteral; |
| } |
| |
| if (getNextChar('d', 'D') >= 0) { |
| return TokenNameDoubleLiteral; |
| } else { //make the distinction between octal and float .... |
| boolean isInteger = true; |
| if (getNextChar('.')) { |
| isInteger = false; |
| while (getNextCharAsDigit()){/*empty*/} |
| } |
| if (getNextChar('e', 'E') >= 0) { // consume next character |
| isInteger = false; |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if ((this.currentCharacter == '-') |
| || (this.currentCharacter == '+')) { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } |
| if (!isDigit(this.currentCharacter)) |
| throw new InvalidInputException(INVALID_FLOAT); |
| while (getNextCharAsDigit()){/*empty*/} |
| } |
| if (getNextChar('f', 'F') >= 0) |
| return TokenNameFloatingPointLiteral; |
| if (getNextChar('d', 'D') >= 0 || !isInteger) |
| return TokenNameDoubleLiteral; |
| return TokenNameIntegerLiteral; |
| } |
| } else { |
| /* carry on */ |
| } |
| } |
| |
| while (getNextCharAsDigit()){/*empty*/} |
| |
| if ((!dotPrefix) && (getNextChar('l', 'L') >= 0)) |
| return TokenNameLongLiteral; |
| |
| if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty |
| while (getNextCharAsDigit()){/*empty*/} |
| floating = true; |
| } |
| |
| //if floating is true both exponant and suffix may be optional |
| |
| if (getNextChar('e', 'E') >= 0) { |
| floating = true; |
| // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| |
| if ((this.currentCharacter == '-') |
| || (this.currentCharacter == '+')) { // consume next character |
| this.unicodeAsBackSlash = false; |
| if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') |
| && (this.source[this.currentPosition] == 'u')) { |
| getNextUnicodeChar(); |
| } else { |
| if (this.withoutUnicodePtr != 0) { |
| unicodeStore(); |
| } |
| } |
| } |
| if (!isDigit(this.currentCharacter)) |
| throw new InvalidInputException(INVALID_FLOAT); |
| while (getNextCharAsDigit()){/*empty*/} |
| } |
| |
| if (getNextChar('d', 'D') >= 0) |
| return TokenNameDoubleLiteral; |
| if (getNextChar('f', 'F') >= 0) |
| return TokenNameFloatingPointLiteral; |
| |
| //the long flag has been tested before |
| |
| return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral; |
| } |
| /** |
| * Search the line number corresponding to a specific position |
| * @param position int |
| * @return int |
| */ |
| public final int getLineNumber(int position) { |
| |
| if (this.lineEnds == null) |
| return 1; |
| int length = this.linePtr+1; |
| if (length == 0) |
| return 1; |
| int g = 0, d = length - 1; |
| int m = 0; |
| while (g <= d) { |
| m = (g + d) /2; |
| if (position < this.lineEnds[m]) { |
| d = m-1; |
| } else if (position > this.lineEnds[m]) { |
| g = m+1; |
| } else { |
| return m + 1; |
| } |
| } |
| if (position < this.lineEnds[m]) { |
| return m+1; |
| } |
| return m+2; |
| } |
| public final void setSource(char[] sourceString){ |
| //the source-buffer is set to sourceString |
| |
| int sourceLength; |
| if (sourceString == null) { |
| this.source = CharOperation.NO_CHAR; |
| sourceLength = 0; |
| } else { |
| this.source = sourceString; |
| sourceLength = sourceString.length; |
| } |
| this.startPosition = -1; |
| this.eofPosition = sourceLength; |
| this.initialPosition = this.currentPosition = 0; |
| this.containsAssertKeyword = false; |
| this.linePtr = -1; |
| } |
| |
| /* |
| * Should be used if a parse (usually a diet parse) has already been performed on the unit, |
| * so as to get the already computed line end positions. |
| */ |
| public final void setSource(CompilationResult compilationResult) { |
| char[] contents = compilationResult.compilationUnit.getContents(); |
| setSource(contents); |
| int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions; |
| if (lineSeparatorPositions != null) { |
| this.lineEnds = lineSeparatorPositions; |
| this.linePtr = lineSeparatorPositions.length - 1; |
| } |
| } |
| public String toString() { |
| if (this.startPosition == this.source.length) |
| return "EOF\n\n" + new String(this.source); //$NON-NLS-1$ |
| if (this.currentPosition > this.source.length) |
| return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$ |
| |
| char front[] = new char[this.startPosition]; |
| System.arraycopy(this.source, 0, front, 0, this.startPosition); |
| |
| int middleLength = (this.currentPosition - 1) - this.startPosition + 1; |
| char middle[]; |
| if (middleLength > -1) { |
| middle = new char[middleLength]; |
| System.arraycopy( |
| this.source, |
| this.startPosition, |
| middle, |
| 0, |
| middleLength); |
| } else { |
| middle = CharOperation.NO_CHAR; |
| } |
| |
| char end[] = new char[this.source.length - (this.currentPosition - 1)]; |
| System.arraycopy( |
| this.source, |
| (this.currentPosition - 1) + 1, |
| end, |
| 0, |
| this.source.length - (this.currentPosition - 1) - 1); |
| |
| return new String(front) |
| + "\n===============================\nStarts here -->" //$NON-NLS-1$ |
| + new String(middle) |
| + "<-- Ends here\n===============================\n" //$NON-NLS-1$ |
| + new String(end); |
| } |
| public String toStringAction(int act) { |
| switch (act) { |
| case TokenNameIdentifier : |
| return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameabstract : |
| return "abstract"; //$NON-NLS-1$ |
| case TokenNameboolean : |
| return "boolean"; //$NON-NLS-1$ |
| case TokenNamebreak : |
| return "break"; //$NON-NLS-1$ |
| case TokenNamebyte : |
| return "byte"; //$NON-NLS-1$ |
| case TokenNamecase : |
| return "case"; //$NON-NLS-1$ |
| case TokenNamecatch : |
| return "catch"; //$NON-NLS-1$ |
| case TokenNamechar : |
| return "char"; //$NON-NLS-1$ |
| case TokenNameclass : |
| return "class"; //$NON-NLS-1$ |
| case TokenNamecontinue : |
| return "continue"; //$NON-NLS-1$ |
| case TokenNamedefault : |
| return "default"; //$NON-NLS-1$ |
| case TokenNamedo : |
| return "do"; //$NON-NLS-1$ |
| case TokenNamedouble : |
| return "double"; //$NON-NLS-1$ |
| case TokenNameelse : |
| return "else"; //$NON-NLS-1$ |
| case TokenNameextends : |
| return "extends"; //$NON-NLS-1$ |
| case TokenNamefalse : |
| return "false"; //$NON-NLS-1$ |
| case TokenNamefinal : |
| return "final"; //$NON-NLS-1$ |
| case TokenNamefinally : |
| return "finally"; //$NON-NLS-1$ |
| case TokenNamefloat : |
| return "float"; //$NON-NLS-1$ |
| case TokenNamefor : |
| return "for"; //$NON-NLS-1$ |
| case TokenNameif : |
| return "if"; //$NON-NLS-1$ |
| case TokenNameimplements : |
| return "implements"; //$NON-NLS-1$ |
| case TokenNameimport : |
| return "import"; //$NON-NLS-1$ |
| case TokenNameinstanceof : |
| return "instanceof"; //$NON-NLS-1$ |
| case TokenNameint : |
| return "int"; //$NON-NLS-1$ |
| case TokenNameinterface : |
| return "interface"; //$NON-NLS-1$ |
| case TokenNamelong : |
| return "long"; //$NON-NLS-1$ |
| case TokenNamenative : |
| return "native"; //$NON-NLS-1$ |
| case TokenNamenew : |
| return "new"; //$NON-NLS-1$ |
| case TokenNamenull : |
| return "null"; //$NON-NLS-1$ |
| case TokenNamepackage : |
| return "package"; //$NON-NLS-1$ |
| case TokenNameprivate : |
| return "private"; //$NON-NLS-1$ |
| case TokenNameprotected : |
| return "protected"; //$NON-NLS-1$ |
| case TokenNamepublic : |
| return "public"; //$NON-NLS-1$ |
| case TokenNamereturn : |
| return "return"; //$NON-NLS-1$ |
| case TokenNameshort : |
| return "short"; //$NON-NLS-1$ |
| case TokenNamestatic : |
| return "static"; //$NON-NLS-1$ |
| case TokenNamesuper : |
| return "super"; //$NON-NLS-1$ |
| case TokenNameswitch : |
| return "switch"; //$NON-NLS-1$ |
| case TokenNamesynchronized : |
| return "synchronized"; //$NON-NLS-1$ |
| case TokenNamethis : |
| return "this"; //$NON-NLS-1$ |
| case TokenNamethrow : |
| return "throw"; //$NON-NLS-1$ |
| case TokenNamethrows : |
| return "throws"; //$NON-NLS-1$ |
| case TokenNametransient : |
| return "transient"; //$NON-NLS-1$ |
| case TokenNametrue : |
| return "true"; //$NON-NLS-1$ |
| case TokenNametry : |
| return "try"; //$NON-NLS-1$ |
| case TokenNamevoid : |
| return "void"; //$NON-NLS-1$ |
| case TokenNamevolatile : |
| return "volatile"; //$NON-NLS-1$ |
| case TokenNamewhile : |
| return "while"; //$NON-NLS-1$ |
| |
| case TokenNameIntegerLiteral : |
| return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameLongLiteral : |
| return "Long(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameFloatingPointLiteral : |
| return "Float(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameDoubleLiteral : |
| return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameCharacterLiteral : |
| return "Char(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| case TokenNameStringLiteral : |
| return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| case TokenNamePLUS_PLUS : |
| return "++"; //$NON-NLS-1$ |
| case TokenNameMINUS_MINUS : |
| return "--"; //$NON-NLS-1$ |
| case TokenNameEQUAL_EQUAL : |
| return "=="; //$NON-NLS-1$ |
| case TokenNameLESS_EQUAL : |
| return "<="; //$NON-NLS-1$ |
| case TokenNameGREATER_EQUAL : |
| return ">="; //$NON-NLS-1$ |
| case TokenNameNOT_EQUAL : |
| return "!="; //$NON-NLS-1$ |
| case TokenNameLEFT_SHIFT : |
| return "<<"; //$NON-NLS-1$ |
| case TokenNameRIGHT_SHIFT : |
| return ">>"; //$NON-NLS-1$ |
| case TokenNameUNSIGNED_RIGHT_SHIFT : |
| return ">>>"; //$NON-NLS-1$ |
| case TokenNamePLUS_EQUAL : |
| return "+="; //$NON-NLS-1$ |
| case TokenNameMINUS_EQUAL : |
| return "-="; //$NON-NLS-1$ |
| case TokenNameMULTIPLY_EQUAL : |
| return "*="; //$NON-NLS-1$ |
| case TokenNameDIVIDE_EQUAL : |
| return "/="; //$NON-NLS-1$ |
| case TokenNameAND_EQUAL : |
| return "&="; //$NON-NLS-1$ |
| case TokenNameOR_EQUAL : |
| return "|="; //$NON-NLS-1$ |
| case TokenNameXOR_EQUAL : |
| return "^="; //$NON-NLS-1$ |
| case TokenNameREMAINDER_EQUAL : |
| return "%="; //$NON-NLS-1$ |
| case TokenNameLEFT_SHIFT_EQUAL : |
| return "<<="; //$NON-NLS-1$ |
| case TokenNameRIGHT_SHIFT_EQUAL : |
| return ">>="; //$NON-NLS-1$ |
| case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : |
| return ">>>="; //$NON-NLS-1$ |
| case TokenNameOR_OR : |
| return "||"; //$NON-NLS-1$ |
| case TokenNameAND_AND : |
| return "&&"; //$NON-NLS-1$ |
| case TokenNamePLUS : |
| return "+"; //$NON-NLS-1$ |
| case TokenNameMINUS : |
| return "-"; //$NON-NLS-1$ |
| case TokenNameNOT : |
| return "!"; //$NON-NLS-1$ |
| case TokenNameREMAINDER : |
| return "%"; //$NON-NLS-1$ |
| case TokenNameXOR : |
| return "^"; //$NON-NLS-1$ |
| case TokenNameAND : |
| return "&"; //$NON-NLS-1$ |
| case TokenNameMULTIPLY : |
| return "*"; //$NON-NLS-1$ |
| case TokenNameOR : |
| return "|"; //$NON-NLS-1$ |
| case TokenNameTWIDDLE : |
| return "~"; //$NON-NLS-1$ |
| case TokenNameDIVIDE : |
| return "/"; //$NON-NLS-1$ |
| case TokenNameGREATER : |
| return ">"; //$NON-NLS-1$ |
| case TokenNameLESS : |
| return "<"; //$NON-NLS-1$ |
| case TokenNameLPAREN : |
| return "("; //$NON-NLS-1$ |
| case TokenNameRPAREN : |
| return ")"; //$NON-NLS-1$ |
| case TokenNameLBRACE : |
| return "{"; //$NON-NLS-1$ |
| case TokenNameRBRACE : |
| return "}"; //$NON-NLS-1$ |
| case TokenNameLBRACKET : |
| return "["; //$NON-NLS-1$ |
| case TokenNameRBRACKET : |
| return "]"; //$NON-NLS-1$ |
| case TokenNameSEMICOLON : |
| return ";"; //$NON-NLS-1$ |
| case TokenNameQUESTION : |
| return "?"; //$NON-NLS-1$ |
| case TokenNameCOLON : |
| return ":"; //$NON-NLS-1$ |
| case TokenNameCOMMA : |
| return ","; //$NON-NLS-1$ |
| case TokenNameDOT : |
| return "."; //$NON-NLS-1$ |
| case TokenNameEQUAL : |
| return "="; //$NON-NLS-1$ |
| case TokenNameEOF : |
| return "EOF"; //$NON-NLS-1$ |
| case TokenNameWHITESPACE : |
| return "white_space(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
| default : |
| return "not-a-token"; //$NON-NLS-1$ |
| } |
| } |
| public void unicodeInitializeBuffer(int length) { |
| this.withoutUnicodePtr = length; |
| if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[length+(1+10)]; |
| int bLength = this.withoutUnicodeBuffer.length; |
| if (1+length >= bLength) { |
| System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length + (1+10)], 0, bLength); |
| } |
| System.arraycopy(this.source, this.startPosition, this.withoutUnicodeBuffer, 1, length); |
| } |
| public void unicodeStore() { |
| int pos = ++this.withoutUnicodePtr; |
| if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10]; |
| int length = this.withoutUnicodeBuffer.length; |
| if (pos == length) { |
| System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length); |
| } |
| this.withoutUnicodeBuffer[pos] = this.currentCharacter; |
| } |
| } |