improved parser keywords abstract, final, public, protected, privatem,..
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Scanner.java
index 3391262..d7c2618 100644 (file)
@@ -14,24 +14,24 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.IScanner;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
 
 public class Scanner implements IScanner, ITerminalSymbols {
 
-  /* 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 
-  */
+  /*
+   * 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
+   */
 
-  // 1.4 feature 
+  // 1.4 feature
   private boolean assertMode;
   public boolean useAssertAsAnIndentifier = false;
-  //flag indicating if processed source contains occurrences of keyword assert 
+  //flag indicating if processed source contains occurrences of keyword assert
   public boolean containsAssertKeyword = false;
 
   public boolean recordLineSeparator;
@@ -67,7 +67,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   //diet parsing support - jump over some method body when requested
   public boolean diet = false;
 
-  //support for the  poor-line-debuggers ....
+  //support for the poor-line-debuggers ....
   //remember the position of the cr/lf
   public int[] lineEnds = new int[250];
   public int linePtr = -1;
@@ -120,7 +120,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   static final int TableSize = 30, InternalTableSize = 6;
   //30*6 = 180 entries
   public static final int OptimizedLength = 6;
-  public /*static*/
+  public /* static */
   final char[][][][] charArray_length = new char[OptimizedLength][TableSize][InternalTableSize][];
   // support for detecting non-externalized string literals
   int currentLineNr = -1;
@@ -135,7 +135,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   public boolean checkNonExternalizedStringLiterals = true;
   public boolean wasNonExternalizedStringLiteral = false;
 
-  /*static*/ {
+  /* static */ {
     for (int i = 0; i < 6; i++) {
       for (int j = 0; j < TableSize; j++) {
         for (int k = 0; k < InternalTableSize; k++) {
@@ -151,7 +151,16 @@ public class Scanner implements IScanner, ITerminalSymbols {
   public static final int CurlyBracket = 2;
   public static final int BracketKinds = 3;
 
-  public static final boolean DEBUG = false;
+  // 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 static final boolean DEBUG = true;
 
   public Scanner() {
     this(false, false);
@@ -161,23 +170,21 @@ public class Scanner implements IScanner, ITerminalSymbols {
   }
 
   /**
-   * Determines if the specified character is
-   * permissible as the first character in a PHP identifier
+   * Determines if the specified character is permissible as the first character in a PHP identifier
    */
   public static boolean isPHPIdentifierStart(char ch) {
     return Character.isLetter(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
   }
 
   /**
-   * Determines if the specified character may be part of a PHP identifier as
-   * other than the first character
+   * Determines if the specified character may be part of a PHP identifier as other than the first character
    */
   public static boolean isPHPIdentifierPart(char ch) {
     return Character.isLetterOrDigit(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF);
   }
 
   public final boolean atEnd() {
-    // This code is not relevant if source is 
+    // This code is not relevant if source is
     // Only a part of the real stream input
 
     return source.length == currentPosition;
@@ -218,8 +225,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   public int getCurrentTokenEndPosition() {
     return this.currentPosition - 1;
   }
-  
-  
+
   public final char[] getCurrentTokenSource() {
     // Return the token REAL source (aka unicodes are precomputed)
 
@@ -277,24 +283,23 @@ public class Scanner implements IScanner, ITerminalSymbols {
   public int getCurrentTokenStartPosition() {
     return this.startPosition;
   }
-  
-       public final char[] getCurrentStringLiteralSource() {
-               // Return the token REAL source (aka unicodes are precomputed)
 
-               char[] result;
+  public final char[] getCurrentStringLiteralSource() {
+    // Return the token REAL source (aka unicodes are precomputed)
+
+    char[] result;
 
-               int length;
-               System.arraycopy(source, startPosition+1, result = new char[length = currentPosition - startPosition - 2], 0, length);
-               //    }
-               return result;
-       }
+    int length;
+    System.arraycopy(source, startPosition + 1, result = new char[length = currentPosition - startPosition - 2], 0, length);
+    //    }
+    return result;
+  }
 
   /*
    * 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.
-   *
+   * 
+   * 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) {
@@ -313,12 +318,11 @@ public class Scanner implements IScanner, ITerminalSymbols {
   }
   /**
    * 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   i.e. first line starts at character 0.
-   *
+   * 
+   * Line numbers are 1-based, and relative to the scanner initialPosition. Character positions are 0-based.
+   * 
+   * e.g. getLineStart(1) --> 0 i.e. first line starts at character 0.
+   * 
    * In case the given line number is inconsistent, answers -1.
    */
   public final int getLineStart(int lineNumber) {
@@ -344,7 +348,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     //Both previous lines are true if the currentCharacter is == to the testedChar
     //On false, no side effect has occured.
 
-    //ALL getNextChar.... ARE OPTIMIZED COPIES 
+    //ALL getNextChar.... ARE OPTIMIZED COPIES
 
     int temp = currentPosition;
     try {
@@ -421,7 +425,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     //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 
+    //ALL getNextChar.... ARE OPTIMIZED COPIES
 
     int temp = currentPosition;
     try {
@@ -503,7 +507,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     //Both previous lines are true if the currentCharacter is a digit
     //On false, no side effect has occured.
 
-    //ALL getNextChar.... ARE OPTIMIZED COPIES 
+    //ALL getNextChar.... ARE OPTIMIZED COPIES
 
     int temp = currentPosition;
     try {
@@ -575,7 +579,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     //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 
+    //ALL getNextChar.... ARE OPTIMIZED COPIES
 
     int temp = currentPosition;
     try {
@@ -647,7 +651,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     //Both previous lines are true if the currentCharacter is a JavaIdentifierPart
     //On false, no side effect has occured.
 
-    //ALL getNextChar.... ARE OPTIMIZED COPIES 
+    //ALL getNextChar.... ARE OPTIMIZED COPIES
 
     int temp = currentPosition;
     try {
@@ -737,7 +741,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 if (test >= 0) {
                   test = getNextChar('P', 'p');
                   if (test >= 0) {
-                    // <?PHP  <?php
+                    // <?PHP <?php
                     startPosition = currentPosition;
                     phpMode = true;
 
@@ -865,8 +869,12 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 return TokenNameTWIDDLE_EQUAL;
               return TokenNameTWIDDLE;
             case '!' :
-              if (getNextChar('='))
+              if (getNextChar('=')) {
+                if (getNextChar('=')) {
+                  return TokenNameNOT_EQUAL_EQUAL;
+                }
                 return TokenNameNOT_EQUAL;
+              }
               return TokenNameNOT;
             case '*' :
               if (getNextChar('='))
@@ -946,8 +954,12 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 return TokenNameGREATER;
               }
             case '=' :
-              if (getNextChar('='))
+              if (getNextChar('=')) {
+                if (getNextChar('=')) {
+                  return TokenNameEQUAL_EQUAL_EQUAL;
+                }
                 return TokenNameEQUAL_EQUAL;
+              }
               if (getNextChar('>'))
                 return TokenNameEQUAL_GREATER;
               return TokenNameEQUAL;
@@ -1045,8 +1057,8 @@ public class Scanner implements IScanner, ITerminalSymbols {
               //                                                               }
               //                                                       }
               //                                               }
-              //                                               //            if (getNextChar('\''))
-              //                                               //              return TokenNameCharacterLiteral;
+              //                                               // 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 (currentPosition + lookAhead == source.length)
@@ -1076,7 +1088,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
 
                 while (currentCharacter != '\'') {
 
-                  /**** in PHP \r and \n are valid in string literals ****/
+                  /** ** in PHP \r and \n are valid in string literals *** */
                   //                  if ((currentCharacter == '\n')
                   //                    || (currentCharacter == '\r')) {
                   //                    // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
@@ -1142,7 +1154,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 }
                 throw e; // rethrow
               }
-              if (checkNonExternalizedStringLiterals) { // check for presence of       NLS tags //$NON-NLS-?$ where ? is an int.
+              if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags //$NON-NLS-?$ where ? is an int.
                 if (currentLine == null) {
                   currentLine = new NLSLine();
                   lines.add(currentLine);
@@ -1167,7 +1179,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
 
                 while (currentCharacter != '"') {
 
-                  /**** in PHP \r and \n are valid in string literals ****/
+                  /** ** in PHP \r and \n are valid in string literals *** */
                   //                  if ((currentCharacter == '\n')
                   //                    || (currentCharacter == '\r')) {
                   //                    // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
@@ -1233,7 +1245,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 }
                 throw e; // rethrow
               }
-              if (checkNonExternalizedStringLiterals) { // check for presence of       NLS tags //$NON-NLS-?$ where ? is an int.
+              if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags //$NON-NLS-?$ where ? is an int.
                 if (currentLine == null) {
                   currentLine = new NLSLine();
                   lines.add(currentLine);
@@ -1258,7 +1270,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
 
                 while (currentCharacter != '`') {
 
-                  /**** in PHP \r and \n are valid in string literals ****/
+                  /** ** in PHP \r and \n are valid in string literals *** */
                   //                if ((currentCharacter == '\n')
                   //                  || (currentCharacter == '\r')) {
                   //                  // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
@@ -1324,7 +1336,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 }
                 throw e; // rethrow
               }
-              if (checkNonExternalizedStringLiterals) { // check for presence of       NLS tags //$NON-NLS-?$ where ? is an int.
+              if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags //$NON-NLS-?$ where ? is an int.
                 if (currentLine == null) {
                   currentLine = new NLSLine();
                   lines.add(currentLine);
@@ -1337,9 +1349,9 @@ public class Scanner implements IScanner, ITerminalSymbols {
               {
                 int test;
                 if ((currentCharacter == '#') || (test = getNextChar('/', '*')) == 0) {
-                  //line comment 
+                  //line comment
                   int endPositionForLineComment = 0;
-                  try { //get the next char 
+                  try { //get the next char
                     currentCharacter = source[currentPosition++];
                     //                    if (((currentCharacter = source[currentPosition++])
                     //                      == '\\')
@@ -1494,7 +1506,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                       currentLine = null;
                     }
                   }
-                  try { //get the next char 
+                  try { //get the next char
                     currentCharacter = source[currentPosition++];
                     //                    if (((currentCharacter = source[currentPosition++])
                     //                      == '\\')
@@ -1590,7 +1602,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   //    //At the end of this method currentCharacter holds the new visited char
   //    //and currentPosition points right next after it
   //
-  //    //ALL getNextChar.... ARE OPTIMIZED COPIES 
+  //    //ALL getNextChar.... ARE OPTIMIZED COPIES
   //
   //    int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
   //    currentPosition++;
@@ -1626,7 +1638,8 @@ public class Scanner implements IScanner, ITerminalSymbols {
   //    }
   //    unicodeAsBackSlash = currentCharacter == '\\';
   //  }
-  /* Tokenize a method body, assuming that curly brackets are properly balanced.
+  /*
+   * Tokenize a method body, assuming that curly brackets are properly balanced.
    */
   public final void jumpOverMethodBody() {
 
@@ -1740,9 +1753,9 @@ public class Scanner implements IScanner, ITerminalSymbols {
             {
               int test;
               if ((test = getNextChar('/', '*')) == 0) {
-                //line comment 
+                //line comment
                 try {
-                  //get the next char 
+                  //get the next char
                   currentCharacter = source[currentPosition++];
                   //                  if (((currentCharacter = source[currentPosition++]) == '\\')
                   //                    && (source[currentPosition] == 'u')) {
@@ -1778,7 +1791,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                   //                  }
 
                   while (currentCharacter != '\r' && currentCharacter != '\n') {
-                    //get the next char 
+                    //get the next char
                     currentCharacter = source[currentPosition++];
                     //                    if (((currentCharacter = source[currentPosition++])
                     //                      == '\\')
@@ -1841,7 +1854,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                 }
                 if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
                   pushLineSeparator();
-                try { //get the next char 
+                try { //get the next char
                   currentCharacter = source[currentPosition++];
                   //                  if (((currentCharacter = source[currentPosition++]) == '\\')
                   //                    && (source[currentPosition] == 'u')) {
@@ -1875,7 +1888,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
                   //                        (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
                   //                    }
                   //                  }
-                  //loop until end of comment */ 
+                  //loop until end of comment */
                   while ((currentCharacter != '/') || (!star)) {
                     if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
                       pushLineSeparator();
@@ -1992,7 +2005,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   //    }
   //  }
   public final int[] getLineEnds() {
-    //return a bounded copy of this.lineEnds 
+    //return a bounded copy of this.lineEnds
 
     int[] copy;
     System.arraycopy(lineEnds, 0, copy = new int[linePtr + 1], 0, linePtr + 1);
@@ -2271,7 +2284,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
       // look-ahead for merged cr+lf
       try {
         if (source[currentPosition] == '\n') {
-          //System.out.println("look-ahead LF-" + currentPosition);                    
+          //System.out.println("look-ahead LF-" + currentPosition);
           lineEnds[linePtr] = currentPosition;
           currentPosition++;
           wasAcr = false;
@@ -2286,13 +2299,13 @@ public class Scanner implements IScanner, ITerminalSymbols {
       if (currentCharacter == '\n') {
         //must merge eventual cr followed by lf
         if (wasAcr && (lineEnds[linePtr] == (currentPosition - 2))) {
-          //System.out.println("merge LF-" + (currentPosition - 1));                                                   
+          //System.out.println("merge LF-" + (currentPosition - 1));
           lineEnds[linePtr] = currentPosition - 1;
         } else {
           int separatorPos = currentPosition - 1;
           if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
             return;
-          // System.out.println("LF-" + separatorPos);                                                 
+          // System.out.println("LF-" + separatorPos);
           try {
             lineEnds[++linePtr] = separatorPos;
           } catch (IndexOutOfBoundsException e) {
@@ -2339,7 +2352,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
       }
       // look-ahead for merged cr+lf
       if (source[currentPosition] == '\n') {
-        //System.out.println("look-ahead LF-" + currentPosition);                      
+        //System.out.println("look-ahead LF-" + currentPosition);
         lineEnds[linePtr] = currentPosition;
         currentPosition++;
         wasAcr = false;
@@ -2351,13 +2364,13 @@ public class Scanner implements IScanner, ITerminalSymbols {
       if (currentCharacter == '\n') {
         //must merge eventual cr followed by lf
         if (wasAcr && (lineEnds[linePtr] == (currentPosition - 7))) {
-          //System.out.println("merge LF-" + (currentPosition - 1));                                                   
+          //System.out.println("merge LF-" + (currentPosition - 1));
           lineEnds[linePtr] = currentPosition - 6;
         } else {
           int separatorPos = currentPosition - 6;
           if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
             return;
-          // System.out.println("LF-" + separatorPos);                                                 
+          // System.out.println("LF-" + separatorPos);
           try {
             lineEnds[++linePtr] = separatorPos;
           } catch (IndexOutOfBoundsException e) {
@@ -2505,7 +2518,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
               } else { // has read \OctalDigit NonDigit--> ignore last character
                 currentPosition--;
               }
-            } else { // has read \OctalDigit NonOctalDigit--> ignore last character                                            
+            } else { // has read \OctalDigit NonOctalDigit--> ignore last character
               currentPosition--;
             }
           } else { // has read \OctalDigit --> ignore last character
@@ -2538,6 +2551,9 @@ public class Scanner implements IScanner, ITerminalSymbols {
     };
 
     if (isVariable) {
+      if (new String(getCurrentTokenSource()).equals("$this")) {
+        return TokenNamethis;
+      }
       return TokenNameVariable;
     }
     int index, length;
@@ -2573,7 +2589,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
     firstLetter = data[index];
     switch (firstLetter) {
 
-      case 'a' : // as and array
+      case 'a' : // as and array abstract
         switch (length) {
           case 2 : //as
             if ((data[++index] == 's')) {
@@ -2587,11 +2603,22 @@ public class Scanner implements IScanner, ITerminalSymbols {
             } else {
               return TokenNameIdentifier;
             }
-            //          case 5 :
-            //            if ((data[++index] == 'r') && (data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'y'))
-            //              return TokenNamearray;
-            //            else
-            //              return TokenNameIdentifier;
+          case 5 : // array
+            if ((data[++index] == 'r') && (data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'y'))
+              return TokenNamearray;
+            else
+              return TokenNameIdentifier;
+          case 8 :
+            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;
           default :
             return TokenNameIdentifier;
         }
@@ -2606,7 +2633,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
             return TokenNameIdentifier;
         }
 
-      case 'c' : //case class continue
+      case 'c' : //case catch class const continue
         switch (length) {
           case 4 :
             if ((data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 'e'))
@@ -2614,8 +2641,12 @@ public class Scanner implements IScanner, ITerminalSymbols {
             else
               return TokenNameIdentifier;
           case 5 :
-            if ((data[++index] == 'l') && (data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 's'))
+            if ((data[++index] == 'a') && (data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
+              return TokenNamecatch;
+            if ((data[index] == 'l') && (data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 's'))
               return TokenNameclass;
+            if ((data[index] == 'o') && (data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 't'))
+              return TokenNameconst;
             else
               return TokenNameIdentifier;
           case 8 :
@@ -2633,13 +2664,18 @@ public class Scanner implements IScanner, ITerminalSymbols {
             return TokenNameIdentifier;
         }
 
-      case 'd' : //define default do 
+      case 'd' : //define declare default do die
         switch (length) {
           case 2 :
             if ((data[++index] == 'o'))
               return TokenNamedo;
             else
               return TokenNameIdentifier;
+          case 3 :
+            if ((data[++index] == 'i') && (data[++index] == 'e'))
+              return TokenNamedie;
+            else
+              return TokenNameIdentifier;
           case 6 :
             if ((data[++index] == 'e')
               && (data[++index] == 'f')
@@ -2651,6 +2687,14 @@ public class Scanner implements IScanner, ITerminalSymbols {
               return TokenNameIdentifier;
           case 7 :
             if ((data[++index] == 'e')
+              && (data[++index] == 'c')
+              && (data[++index] == 'l')
+              && (data[++index] == 'a')
+              && (data[++index] == 'r')
+              && (data[++index] == 'e'))
+              return TokenNamedeclare;
+            index = 0;
+            if ((data[++index] == 'e')
               && (data[++index] == 'f')
               && (data[++index] == 'a')
               && (data[++index] == 'u')
@@ -2662,18 +2706,24 @@ public class Scanner implements IScanner, ITerminalSymbols {
           default :
             return TokenNameIdentifier;
         }
-      case 'e' : //echo else elseif extends
+      case 'e' : //echo else exit elseif extends eval
         switch (length) {
           case 4 :
             if ((data[++index] == 'c') && (data[++index] == 'h') && (data[++index] == 'o'))
               return TokenNameecho;
             else if ((data[index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
               return TokenNameelse;
+            else if ((data[index] == 'x') && (data[++index] == 'i') && (data[++index] == 't'))
+              return TokenNameexit;
+            else if ((data[index] == 'v') && (data[++index] == 'a') && (data[++index] == 'l'))
+              return TokenNameeval;
             else
               return TokenNameIdentifier;
-          case 5 : // endif
+          case 5 : // endif empty
             if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'i') && (data[++index] == 'f'))
               return TokenNameendif;
+            if ((data[index] == 'm') && (data[++index] == 'p') && (data[++index] == 't') && (data[++index] == 'y'))
+              return TokenNameempty;
             else
               return TokenNameIdentifier;
           case 6 : // endfor
@@ -2725,9 +2775,20 @@ public class Scanner implements IScanner, ITerminalSymbols {
               return TokenNameendswitch;
             else
               return TokenNameIdentifier;
-          case 10 : // endforeach
+          case 10 : // enddeclare
             if ((data[++index] == 'n')
               && (data[++index] == 'd')
+              && (data[++index] == 'd')
+              && (data[++index] == 'e')
+              && (data[++index] == 'c')
+              && (data[++index] == 'l')
+              && (data[++index] == 'a')
+              && (data[++index] == 'r')
+              && (data[++index] == 'e'))
+              return TokenNameendforeach;
+            index = 0;
+            if ((data[++index] == 'n') // endforeach
+              && (data[++index] == 'd')
               && (data[++index] == 'f')
               && (data[++index] == 'o')
               && (data[++index] == 'r')
@@ -2743,7 +2804,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
             return TokenNameIdentifier;
         }
 
-      case 'f' : //for false function
+      case 'f' : //for false final function
         switch (length) {
           case 3 :
             if ((data[++index] == 'o') && (data[++index] == 'r'))
@@ -2753,9 +2814,11 @@ public class Scanner implements IScanner, ITerminalSymbols {
           case 5 :
             if ((data[++index] == 'a') && (data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
               return TokenNamefalse;
+            if ((data[index] == 'i') && (data[++index] == 'n') && (data[++index] == 'a') && (data[++index] == 'l'))
+              return TokenNamefinal;
             else
               return TokenNameIdentifier;
-          case 7 : // function
+          case 7 : // foreach
             if ((data[++index] == 'o')
               && (data[++index] == 'r')
               && (data[++index] == 'e')
@@ -2791,7 +2854,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
         }
         return TokenNameIdentifier;
 
-      case 'i' : //if int 
+      case 'i' : //if int isset include include_once instanceof interface implements
         switch (length) {
           case 2 :
             if (data[++index] == 'f')
@@ -2803,6 +2866,11 @@ public class Scanner implements IScanner, ITerminalSymbols {
             //              return TokenNameint;
             //            else
             //              return TokenNameIdentifier;
+          case 5 :
+            if ((data[++index] == 's') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 't'))
+              return TokenNameisset;
+            else
+              return TokenNameIdentifier;
           case 7 :
             if ((data[++index] == 'n')
               && (data[++index] == 'c')
@@ -2813,6 +2881,41 @@ public class Scanner implements IScanner, ITerminalSymbols {
               return TokenNameinclude;
             else
               return TokenNameIdentifier;
+          case 9 : // interface
+            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 : // instanceof
+            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;
+            if ((data[index] == 'm')
+              && (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;
           case 12 :
             if ((data[++index] == 'n')
               && (data[++index] == 'c')
@@ -2879,11 +2982,44 @@ public class Scanner implements IScanner, ITerminalSymbols {
         //        }
         return TokenNameIdentifier;
 
-      case 'p' : // print
-        if (length == 5) {
-          if ((data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 't')) {
-            return TokenNameprint;
-          }
+      case 'p' : // print public private protected
+        switch (length) {
+          case 5 :
+            if ((data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 't')) {
+              return TokenNameprint;
+            } else
+              return TokenNameIdentifier;
+          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] == '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;
         }
         return TokenNameIdentifier;
       case 'r' : //return require require_once
@@ -2921,7 +3057,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
         } else
           return TokenNameIdentifier;
 
-      case 's' : //static switch 
+      case 's' : //static switch
         switch (length) {
           case 6 :
             if (data[++index] == 't')
@@ -2942,22 +3078,43 @@ public class Scanner implements IScanner, ITerminalSymbols {
             return TokenNameIdentifier;
         }
 
-      case 't' : // true
+      case 't' : // try true throw
         switch (length) {
-
+          case 3 :
+            if ((data[++index] == 'r') && (data[++index] == 'y'))
+              return TokenNametry;
+            else
+              return TokenNameIdentifier;
           case 4 :
             if ((data[++index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e'))
               return TokenNametrue;
             else
               return TokenNameIdentifier;
-            //            if ((data[++index] == 'h') && (data[++index] == 'i') && (data[++index] == 's'))
-            //              return TokenNamethis;
+          case 5 :
+            if ((data[++index] == 'h') && (data[++index] == 'r') && (data[++index] == 'o') && (data[++index] == 'w'))
+              return TokenNamethrow;
+            else
+              return TokenNameIdentifier;
 
           default :
             return TokenNameIdentifier;
         }
-
-      case 'v' : //var 
+      case 'u' : //use unset
+        switch (length) {
+          case 3 :
+            if ((data[++index] == 's') && (data[++index] == 'e'))
+              return TokenNameuse;
+            else
+              return TokenNameIdentifier;
+          case 5 :
+            if ((data[++index] == 'n') && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 't'))
+              return TokenNameunset;
+            else
+              return TokenNameIdentifier;
+          default :
+            return TokenNameIdentifier;
+        }
+      case 'v' : //var
         switch (length) {
           case 3 :
             if ((data[++index] == 'a') && (data[++index] == 'r'))
@@ -2969,14 +3126,15 @@ public class Scanner implements IScanner, ITerminalSymbols {
             return TokenNameIdentifier;
         }
 
-      case 'w' : //while 
+      case 'w' : //while
         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'))
+            //case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&&
+            // (data[++index]=='p'))
             //return TokenNamewidefp ;
             //else
             //return TokenNameIdentifier;
@@ -3154,7 +3312,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
   }
   /**
    * Search the line number corresponding to a specific position
-   *
+   *  
    */
   public final int getLineNumber(int position) {
 
@@ -3229,7 +3387,7 @@ public class Scanner implements IScanner, ITerminalSymbols {
 
     switch (act) {
       case TokenNameERROR :
-        return "ScannerError(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
+        return "ScannerError"; // + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$
       case TokenNameStopPHP :
         return "StopPHP(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
       case TokenNameIdentifier :
@@ -3310,6 +3468,8 @@ public class Scanner implements IScanner, ITerminalSymbols {
         return "var"; //$NON-NLS-1$
       case TokenNamewhile :
         return "while"; //$NON-NLS-1$
+      case TokenNamethis :
+        return "$this"; //$NON-NLS-1$
       case TokenNameIntegerLiteral :
         return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
       case TokenNameDoubleLiteral :
@@ -3329,6 +3489,8 @@ public class Scanner implements IScanner, ITerminalSymbols {
         return "--"; //$NON-NLS-1$
       case TokenNameEQUAL_EQUAL :
         return "=="; //$NON-NLS-1$
+      case TokenNameEQUAL_EQUAL_EQUAL :
+        return "==="; //$NON-NLS-1$
       case TokenNameEQUAL_GREATER :
         return "=>"; //$NON-NLS-1$
       case TokenNameLESS_EQUAL :
@@ -3337,6 +3499,8 @@ public class Scanner implements IScanner, ITerminalSymbols {
         return ">="; //$NON-NLS-1$
       case TokenNameNOT_EQUAL :
         return "!="; //$NON-NLS-1$
+      case TokenNameNOT_EQUAL_EQUAL :
+        return "!=="; //$NON-NLS-1$
       case TokenNameLEFT_SHIFT :
         return "<<"; //$NON-NLS-1$
       case TokenNameRIGHT_SHIFT :
@@ -3500,4 +3664,195 @@ public class Scanner implements IScanner, ITerminalSymbols {
     }
     currentLine = null;
   }
+
+  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).
+
+    if (unicodeAsBackSlash) {
+      // consume next character
+      unicodeAsBackSlash = false;
+      //                       if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+      //                               getNextUnicodeChar();
+      //                       } else {
+      if (withoutUnicodePtr != 0) {
+        withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+        //                             }
+      }
+    } else
+      currentCharacter = source[currentPosition++];
+    switch (currentCharacter) {
+      case 'b' :
+        currentCharacter = '\b';
+        break;
+      case 't' :
+        currentCharacter = '\t';
+        break;
+      case 'n' :
+        currentCharacter = '\n';
+        break;
+      case 'f' :
+        currentCharacter = '\f';
+        break;
+      case 'r' :
+        currentCharacter = '\r';
+        break;
+      case '\"' :
+        currentCharacter = '\"';
+        break;
+      case '\'' :
+        currentCharacter = '\'';
+        break;
+      case '\\' :
+        currentCharacter = '\\';
+        break;
+      default :
+        // -----------octal escape--------------
+        // OctalDigit
+        // OctalDigit OctalDigit
+        // ZeroToThree OctalDigit OctalDigit
+
+        int number = Character.getNumericValue(currentCharacter);
+        if (number >= 0 && number <= 7) {
+          boolean zeroToThreeNot = number > 3;
+          if (Character.isDigit(currentCharacter = source[currentPosition++])) {
+            int digit = Character.getNumericValue(currentCharacter);
+            if (digit >= 0 && digit <= 7) {
+              number = (number * 8) + digit;
+              if (Character.isDigit(currentCharacter = source[currentPosition++])) {
+                if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit Digit --> ignore last character
+                  currentPosition--;
+                } else {
+                  digit = Character.getNumericValue(currentCharacter);
+                  if (digit >= 0 && digit <= 7) { // has read \ZeroToThree OctalDigit OctalDigit
+                    number = (number * 8) + digit;
+                  } else { // has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
+                    currentPosition--;
+                  }
+                }
+              } else { // has read \OctalDigit NonDigit--> ignore last character
+                currentPosition--;
+              }
+            } else { // has read \OctalDigit NonOctalDigit--> ignore last character
+              currentPosition--;
+            }
+          } else { // has read \OctalDigit --> ignore last character
+            currentPosition--;
+          }
+          if (number > 255)
+            throw new InvalidInputException(INVALID_ESCAPE);
+          currentCharacter = (char) number;
+        } else
+          throw new InvalidInputException(INVALID_ESCAPE);
+    }
+  }
+
+  // chech presence of task: tags
+  public void checkTaskTag(int commentStart, int commentEnd) {
+
+    // only look for newer task: tags
+    if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
+      return;
+    }
+    int foundTaskIndex = this.foundTaskCount;
+    nextChar : for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) {
+
+      char[] tag = null;
+      char[] priority = null;
+
+      // check for tag occurrence
+      nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
+        tag = this.taskTags[itag];
+        priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null;
+        int tagLength = tag.length;
+        for (int t = 0; t < tagLength; t++) {
+          if (this.source[i + t] != tag[t])
+            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);
+        }
+        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
+      }
+    }
+
+    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 = this.source[j]) == '\n' || c == '\r') {
+          end = j - 1;
+          break;
+        }
+      }
+
+      if (end == -1) {
+        for (int j = max_value; j > msgStart; j--) {
+          if ((c = this.source[j]) == '*') {
+            end = j - 1;
+            break;
+          }
+        }
+        if (end == -1)
+          end = max_value;
+      }
+
+      if (msgStart == end)
+        continue; // empty
+
+      // trim the message
+      while (CharOperation.isWhitespace(source[end]) && msgStart <= end)
+        end--;
+      while (CharOperation.isWhitespace(source[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(source, msgStart, message, 0, messageLength);
+      this.foundTaskMessages[i] = message;
+    }
+  }
+
 }