import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / parser / Scanner.java
index 70e8242..6ec4cf4 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Iterator;
 
 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;
 
@@ -34,13 +35,15 @@ public class Scanner implements TerminalTokens {
         - 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;
@@ -101,6 +104,7 @@ public class Scanner implements TerminalTokens {
        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'}, 
@@ -137,7 +141,7 @@ public class Scanner implements TerminalTokens {
        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$
@@ -146,6 +150,9 @@ public class Scanner implements TerminalTokens {
        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++) {
@@ -183,7 +190,7 @@ public Scanner(
        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;
@@ -196,7 +203,7 @@ public  final boolean atEnd() {
        return this.source.length == this.currentPosition;
 }
 
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
        if (this.currentLine == null) 
                return;
        parseTags(this.currentLine);
@@ -925,6 +932,13 @@ public int getNextToken() throws InvalidInputException {
                        // ---------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 ')' :
@@ -942,9 +956,37 @@ public int getNextToken() throws InvalidInputException {
                                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;
@@ -992,6 +1034,9 @@ public int getNextToken() throws InvalidInputException {
                                case '>' :
                                        {
                                                int test;
+                                               if (this.returnOnlyGreater) {
+                                                       return TokenNameGREATER;
+                                               }
                                                if ((test = getNextChar('=', '>')) == 0)
                                                        return TokenNameGREATER_EQUAL;
                                                if (test > 0) {
@@ -1367,7 +1412,9 @@ public int getNextToken() throws InvalidInputException {
                                                                if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
                                                                        checkNonExternalizedString();
                                                                        if (this.recordLineSeparator) {
-                                                                               if (!isUnicode) {
+                                                                               if (isUnicode) {
+                                                                                       pushUnicodeLineSeparator();
+                                                                               } else {
                                                                                        pushLineSeparator();
                                                                                }
                                                                        } else {
@@ -1397,7 +1444,9 @@ public int getNextToken() throws InvalidInputException {
                                                                        if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
                                                                                checkNonExternalizedString();
                                                                                if (this.recordLineSeparator) {
-                                                                                       if (!isUnicode) {
+                                                                                       if (isUnicode) {
+                                                                                               pushUnicodeLineSeparator();
+                                                                                       } else {
                                                                                                pushLineSeparator();
                                                                                        }
                                                                                } else {
@@ -1450,8 +1499,9 @@ public int getNextToken() throws InvalidInputException {
                                default :
                                        if (Character.isJavaIdentifierStart(this.currentCharacter))
                                                return scanIdentifierOrKeyword();
-                                       if (isDigit(this.currentCharacter))
+                                       if (isDigit(this.currentCharacter)) {
                                                return scanNumber(false);
+                                       }                                               
                                        return TokenNameERROR;
                        }
                }
@@ -1513,7 +1563,7 @@ public final void getNextUnicodeChar()
 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' :
@@ -1528,7 +1578,7 @@ private boolean isDigit(char c) throws InvalidInputException {
                        case '9' :
                                return true;
                }
-               throw new InvalidInputException(Scanner.INVALID_INPUT);
+               throw new InvalidInputException(Scanner.INVALID_DIGIT);
        } else {
                return false;
        }
@@ -2164,7 +2214,7 @@ final char[] optimizedCurrentTokenSource6() {
        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();
@@ -2413,6 +2463,7 @@ public int scanIdentifierOrKeyword() {
        //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;
@@ -2459,7 +2510,7 @@ public int scanIdentifierOrKeyword() {
                                                && (data[++index] == 'e')
                                                && (data[++index] == 'r')
                                                && (data[++index] == 't')) {
-                                                       if (this.assertMode) {
+                                                       if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
                                                                this.containsAssertKeyword = true;
                                                                return TokenNameassert;
                                                        } else {
@@ -2584,8 +2635,18 @@ public int scanIdentifierOrKeyword() {
                                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')
@@ -2985,25 +3046,114 @@ public int scanNumber(boolean dotPrefix) throws InvalidInputException {
        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
@@ -3161,6 +3311,21 @@ public final void setSource(char[] sourceString){
        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() {
@@ -3200,7 +3365,7 @@ 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$