import org.eclipse.jdt.core.compiler.CharOperation;
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;
- sourceStart gives the position into the stream
- currentPosition-1 gives the sourceEnd position into the stream
*/
-
+ protected long sourceLevel;
// 1.4 feature
- private boolean assertMode = false;
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 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$
//----------------optimized identifier managment------------------
static final char[] charArray_a = new char[] {'a'},
public /*static*/ final char[][][][] charArray_length =
new char[OptimizedLength][TableSize][InternalTableSize][];
// support for detecting non-externalized string literals
- NLSLine currentLine= null;
+ 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 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++) {
this.tokenizeComments = tokenizeComments;
this.tokenizeWhiteSpace = tokenizeWhiteSpace;
this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
- this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
+ this.sourceLevel = sourceLevel;
this.taskTags = taskTags;
this.taskPriorities = taskPriorities;
this.isTaskCaseSensitive = isTaskCaseSensitive;
return this.source.length == this.currentPosition;
}
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
if (this.currentLine == null)
return;
parseTags(this.currentLine);
// ---------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 ')' :
case ',' :
return TokenNameCOMMA;
case '.' :
- if (getNextCharAsDigit())
+ if (getNextCharAsDigit()) {
return scanNumber(true);
- return TokenNameDOT;
+ }
+/* 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;
case '>' :
{
int test;
+ if (this.returnOnlyGreater) {
+ return TokenNameGREATER;
+ }
if ((test = getNextChar('=', '>')) == 0)
return TokenNameGREATER_EQUAL;
if (test > 0) {
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
checkNonExternalizedString();
if (this.recordLineSeparator) {
- if (!isUnicode) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
pushLineSeparator();
}
} else {
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
checkNonExternalizedString();
if (this.recordLineSeparator) {
- if (!isUnicode) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
pushLineSeparator();
}
} else {
default :
if (Character.isJavaIdentifierStart(this.currentCharacter))
return scanIdentifierOrKeyword();
- if (isDigit(this.currentCharacter))
+ if (isDigit(this.currentCharacter)) {
return scanNumber(false);
+ }
return TokenNameERROR;
}
}
public char[] getSource(){
return this.source;
}
-private boolean isDigit(char c) throws InvalidInputException {
+protected boolean isDigit(char c) throws InvalidInputException {
if (Character.isDigit(c)) {
switch(c) {
case '0' :
case '9' :
return true;
}
- throw new InvalidInputException(Scanner.INVALID_INPUT);
+ throw new InvalidInputException(Scanner.INVALID_DIGIT);
} else {
return false;
}
newEntry6 = max;
return r;
}
-private void parseTags(NLSLine line) {
+protected void parseTags(NLSLine line) {
String s = new String(getCurrentTokenSource());
int pos = s.indexOf(TAG_PREFIX);
int lineLength = line.size();
//keywors with the same length AND the same first char, then do another
//dispatch on the second char
this.useAssertAsAnIndentifier = false;
+ this.useEnumAsAnIndentifier = false;
while (getNextCharAsJavaIdentifierPart()){/*empty*/}
int index, length;
&& (data[++index] == 'e')
&& (data[++index] == 'r')
&& (data[++index] == 't')) {
- if (this.assertMode) {
+ if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
this.containsAssertKeyword = true;
return TokenNameassert;
} else {
case 4 :
if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
return TokenNameelse;
- else
- return TokenNameIdentifier;
+ 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')
boolean floating = dotPrefix;
if ((!dotPrefix) && (this.currentCharacter == '0')) {
if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
- //force the first char of the hexa number do exist...
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStoreAt(++this.withoutUnicodePtr);
- }
- }
- if (Character.digit(this.currentCharacter, 16) == -1)
- throw new InvalidInputException(INVALID_HEXA);
- //---end forcing--
+ int start = this.currentPosition;
while (getNextCharAsDigit(16)){/*empty*/}
- if (getNextChar('l', 'L') >= 0)
+ int end = this.currentPosition;
+ if (getNextChar('l', 'L') >= 0) {
+ if (end == start) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
return TokenNameLongLiteral;
- else
+ } else if (getNextChar('.')) {
+ if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+ // if we are in source level < 1.5, we report an integer literal
+ this.currentPosition = end;
+ return TokenNameIntegerLiteral;
+ }
+ // hexadeciman 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) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+
+ 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) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+ }
+ 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) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+
+ 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) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+ }
+ 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
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() {
+ "<-- Ends here\n===============================\n" //$NON-NLS-1$
+ new String(end);
}
-public final String toStringAction(int act) {
+public String toStringAction(int act) {
switch (act) {
case TokenNameIdentifier :
return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$