new PartitionScanner version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / FastJavaPartitionScanner.java
index 70f5461..ed3302f 100644 (file)
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
 package net.sourceforge.phpdt.internal.ui.text;
 
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
+import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
 
+import org.eclipse.jface.text.Assert;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.rules.ICharacterScanner;
 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
 import org.eclipse.jface.text.rules.Token;
 
-
 /**
- * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments,
- * Java strings and Java characters.
+ * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments, Java strings.
  */
-public class FastJavaPartitionScanner implements IPartitionTokenScanner {
-
-//     private final static String SKIP= "__skip"; //$NON-NLS-1$       
-//     public final static String JAVA_STRING= "__php_string"; //$NON-NLS-1$
-//     public final static String JAVA_SINGLE_LINE_COMMENT= "__php_singleline_comment"; //$NON-NLS-1$
-//     public final static String JAVA_MULTI_LINE_COMMENT= "__php_multiline_comment"; //$NON-NLS-1$
-//     public final static String JAVA_DOC= "__php_phpdoc"; //$NON-NLS-1$
-
-       // states
-       private static final int HTML= 0;       
-       private static final int SINGLE_LINE_COMMENT= 1; 
-       private static final int MULTI_LINE_COMMENT= 2;
-       private static final int PHPDOC= 3;
-//     private static final int CHARACTER= 4;
-       private static final int STRING_SQ= 4;  // single quote string
-       private static final int STRING_DQ= 5;  // double quote string
-       private static final int PHP= 6;  // double quote string
-       
-       // beginning of prefixes and postfixes
-       private static final int NONE= 0;
-       private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER
-       private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
-       private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
-       private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
-       private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
-       private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
-       
-       /** The scanner. */
-//     private final BufferedRuleBasedScanner fScanner= new BufferedRuleBasedScanner(1000);
-       private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000);      // faster implementation
-       
-       /** The offset of the last returned token. */
-       private int fTokenOffset;
-       /** The length of the last returned token. */
-       private int fTokenLength;
-       
-       /** The state of the scanner. */        
-       private int fState;
-       /** The last significant characters read. */
-       private int fLast;
-       /** The amount of characters already read on first call to nextToken(). */
-       private int fPrefixLength;
-       
-       // emulate JavaPartitionScanner 
-//     private static final boolean fgEmulate= false;
-       private int fJavaOffset;
-       private int fJavaLength;
-       
-       private final IToken[] fTokens= new IToken[] {
-               new Token(null),
-               new Token(IPHPPartitions.PHP_SINGLELINE_COMMENT),
-               new Token(IPHPPartitions.PHP_MULTILINE_COMMENT),
-               new Token(IPHPPartitions.PHP_PHPDOC_COMMENT),
-               new Token(IPHPPartitions.PHP_STRING_SQ),
-               new Token(IPHPPartitions.PHP_STRING_DQ),
-               new Token(IPHPPartitions.PHP_PARTITIONING),
-       };
-
-       /*
-        * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
-        */
-       public IToken nextToken() {
-
-               fTokenOffset += fTokenLength;
-               fTokenLength= fPrefixLength;
-
-               while (true) {
-                       final int ch= fScanner.read();
-                       
-                       // characters
-                       switch (ch) {
-                       case ICharacterScanner.EOF:
-                               if (fTokenLength > 0) {
-                                       fLast= NONE; // ignore last
-                                       return preFix(fState, HTML, NONE, 0);
-
-                               } else {
-                                       fLast= NONE;
-                                       fPrefixLength= 0;
-                                       return Token.EOF;
-                               }
-
-                       case '\r':
-                               if ( fLast != CARRIAGE_RETURN) {
-                                               fLast= CARRIAGE_RETURN;
-                                               fTokenLength++;
-                                               continue;
-
-                               } else {
-                                       
-                                       switch (fState) {
-                                       case SINGLE_LINE_COMMENT:
-//                                     case CHARACTER:
-                                       case STRING_SQ:  
-                                       case STRING_DQ:
-                                               if (fTokenLength > 0) {
-                                                       IToken token= fTokens[fState];
-                                                       
-                                                       // emulate JavaPartitionScanner
-//                                                     if (fgEmulate) {
-//                                                             fTokenLength++;
-//                                                             fLast= NONE;
-//                                                             fPrefixLength= 0;
-//                                                     } else {                                                                
-                                                               fLast= CARRIAGE_RETURN; 
-                                                               fPrefixLength= 1;
-//                                                     }
-                                                       
-                                                       fState= HTML;
-                                                       return token;
-
-                                               } else {
-                                                       consume();
-                                                       continue;       
-                                               }
-
-                                       default:
-                                               consume();
-                                               continue;
-                                       }                                       
-                               }
-       
-                       case '\n':                              
-                               switch (fState) {
-                               case SINGLE_LINE_COMMENT:
-//                             case CHARACTER:
-                               case STRING_SQ:
-                               case STRING_DQ:                         
-                                       // assert(fTokenLength > 0);
-                                       return postFix(fState);
-
-                               default:
-                                       consume();
-                                       continue;
-                               }
-
-                       default:
-                               if ( fLast == CARRIAGE_RETURN) {                        
-                                       switch (fState) {
-                                       case SINGLE_LINE_COMMENT:
-//                                     case CHARACTER:
-                                       case STRING_SQ:
-                                       case STRING_DQ:
-
-                                               int last;
-                                               int newState;
-                                               switch (ch) {
-                                               case '/':
-                                                       last= SLASH;
-                                                       newState= HTML;
-                                                       break;
-
-                                               case '*':
-                                                       last= STAR;
-                                                       newState= HTML;
-                                                       break;
-                                               
-                                               case '\'':
-                                                       last= NONE;
-       //                                              newState= CHARACTER;
-                                                       newState= STRING_SQ;
-                                                       break;
-
-                                               case '"':
-                                                       last= NONE;
-                                                       newState= STRING_DQ;
-                                                       break;
-
-                                               case '\r':
-                                                       last= CARRIAGE_RETURN;
-                                                       newState= HTML;
-                                                       break;
-
-                                               case '\\':
-                                                       last= BACKSLASH;
-                                                       newState= HTML;
-                                                       break;
-
-                                               default:
-                                                       last= NONE;
-                                                       newState= HTML;
-                                                       break;
-                                               }
-                                               
-                                               fLast= NONE; // ignore fLast
-                                               return preFix(fState, newState, last, 1);
-       
-                                       default:
-                                               break;
-                                       }
-                               }
-                       }
-
-                       // states        
-                       switch (fState) {
-                       case PHP:
-                               switch (ch) {
-                               case '/':
-                                       if (fLast == SLASH) {
-                                               if (fTokenLength - getLastLength(fLast) > 0) {
-                                                       return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
-                                               } else {                                                        
-                                                       preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
-                                                       fTokenOffset += fTokenLength;
-                                                       fTokenLength= fPrefixLength;
-                                                       break;
-                                               }
-       
-                                       } else {
-                                               fTokenLength++;
-                                               fLast= SLASH;
-                                               break;
-                                       }
-       
-                               case '*':
-                                       if (fLast == SLASH) {
-                                               if (fTokenLength - getLastLength(fLast) > 0)
-                                                       return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
-                                               else {
-                                                       preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
-                                                       fTokenOffset += fTokenLength;
-                                                       fTokenLength= fPrefixLength;
-                                                       break;
-                                               }
-
-                                       } else {
-                                               consume();
-                                               break;
-                                       }
-                                       
-                               case '\'':
-                                       fLast= NONE; // ignore fLast
-                                       if (fTokenLength > 0)
-                                               return preFix(PHP, STRING_SQ, NONE, 1);
-                                       else {                                          
-                                               preFix(PHP, STRING_SQ, NONE, 1);
-                                               fTokenOffset += fTokenLength;
-                                               fTokenLength= fPrefixLength;
-                                               break;
-                                       }
-
-                               case '"':
-                                       fLast= NONE; // ignore fLast                            
-                                       if (fTokenLength > 0)
-                                               return preFix(PHP, STRING_DQ, NONE, 1);
-                                       else {
-                                               preFix(PHP, STRING_DQ, NONE, 1);
-                                               fTokenOffset += fTokenLength;
-                                               fTokenLength= fPrefixLength;
-                                               break;
-                                       }
-       
-                               default:
-                                       consume();
-                                       break;
-                               }
-                               break;
-       
-                       case SINGLE_LINE_COMMENT:
-                               consume();
-                               break;
-                               
-                       case PHPDOC:
-                               switch (ch) {
-                               case '/':
-                                       switch (fLast) {
-                                       case SLASH_STAR_STAR:
-                                               return postFix(MULTI_LINE_COMMENT);
-       
-                                       case STAR:
-                                               return postFix(PHPDOC);
-
-                                       default:
-                                               consume();
-                                               break;
-                                       }
-                                       break;
-
-                               case '*':
-                                       fTokenLength++;
-                                       fLast= STAR;
-                                       break;
-
-                               default:
-                                       consume();
-                                       break;
-                               }
-                               break;
-       
-                       case MULTI_LINE_COMMENT:
-                               switch (ch) {
-                               case '*':
-                                       if (fLast == SLASH_STAR) {
-                                               fLast= SLASH_STAR_STAR;
-                                               fTokenLength++;
-                                               fState= PHPDOC;
-                                       } else {
-                                               fTokenLength++;
-                                               fLast= STAR;
-                                       }
-                                       break;
-       
-                               case '/':
-                                       if (fLast == STAR) {
-                                               return postFix(MULTI_LINE_COMMENT);
-                                       } else {
-                                               consume();
-                                               break;
-                                       }
-       
-                               default:
-                                       consume();
-                                       break;                  
-                               }
-                               break;
-                               
-                       case STRING_DQ:
-                               switch (ch) {
-                               case '\\':
-                                       fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
-                                       fTokenLength++;
-                                       break;
-                                       
-                               case '\"':                                                      
-                                       if (fLast != BACKSLASH) {
-                                               return postFix(STRING_DQ);
-
-                                       } else {
-                                               consume();
-                                               break;                                  
-                                       }
-                               
-                               default:
-                                       consume();
-                                       break;
-                               }
-                               break;
-       
-                       case STRING_SQ:
-                               switch (ch) {
-                               case '\\':
-                                       fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
-                                       fTokenLength++;
-                                       break;
-       
-                               case '\'':
-                                       if (fLast != BACKSLASH) {
-                                               return postFix(STRING_SQ);
-       
-                                       } else {
-                                               consume();
-                                               break;
-                                       }
-       
-                               default:
-                                       consume();
-                                       break;
-                               }
-                               break;
-                       }
-               } 
-       }               
-
-       private static final int getLastLength(int last) {
-               switch (last) {
-               default:
-                       return -1;
-
-               case NONE:
-                       return 0;
-                       
-               case CARRIAGE_RETURN:
-               case BACKSLASH:
-               case SLASH:
-               case STAR:
-                       return 1;
-
-               case SLASH_STAR:
-                       return 2;
-
-               case SLASH_STAR_STAR:
-                       return 3;
-               }       
-       }
-
-       private final void consume() {
-               fTokenLength++;
-               fLast= NONE;    
-       }
-       
-       private final IToken postFix(int state) {
-               fTokenLength++;
-               fLast= NONE;
-               fState= HTML;
-               fPrefixLength= 0;               
-               return fTokens[state];
-       }
-
-       private final IToken preFix(int state, int newState, int last, int prefixLength) {
-               // emulate JavaPartitionScanner
-//             if (fgEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) {
-//                     fTokenLength -= getLastLength(fLast);
-//                     fJavaOffset= fTokenOffset;
-//                     fJavaLength= fTokenLength;
-//                     fTokenLength= 1;
-//                     fState= newState;
-//                     fPrefixLength= prefixLength;
-//                     fLast= last;
-//                     return fTokens[state];
-//
-//             } else {
-                       fTokenLength -= getLastLength(fLast);
-                       fLast= last;
-                       fPrefixLength= prefixLength;
-                       IToken token= fTokens[state];           
-                       fState= newState;
-                       return token;
-//             }
-       }
-
-       private static int getState(String contentType) {
-
-               if (contentType == null)
-                       return HTML;
-               
-               else if (contentType.equals(IPHPPartitions.PHP_PARTITIONING))
-                       return PHP;
-               
-               else if (contentType.equals(IPHPPartitions.PHP_SINGLELINE_COMMENT))
-                       return SINGLE_LINE_COMMENT;
-
-               else if (contentType.equals(IPHPPartitions.PHP_MULTILINE_COMMENT))
-                       return MULTI_LINE_COMMENT;
-
-               else if (contentType.equals(IPHPPartitions.PHP_PHPDOC_COMMENT))
-                       return PHPDOC;
-
-               else if (contentType.equals(IPHPPartitions.PHP_STRING_DQ))
-                       return STRING_DQ;
-               
-               else if (contentType.equals(IPHPPartitions.PHP_STRING_SQ))
-                       return STRING_SQ;
-               
-//             else if (contentType.equals(SKIP))
-//                     return CHARACTER;
-                       
-               else
-                       return HTML;
-       }
-
-       /*
-        * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
-        */
-       public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
-
-               fScanner.setRange(document, offset, length);
-               fTokenOffset= partitionOffset;
-               fTokenLength= 0;
-               fPrefixLength= offset - partitionOffset;
-               fLast= NONE;
-               
-               if (offset == partitionOffset) {
-                       // restart at beginning of partition
-                       fState= HTML;
-               } else {
-                       fState= getState(contentType);                  
-               }
-
-               // emulate JavaPartitionScanner
-//             if (fgEmulate) {
-//                     fJavaOffset= -1;
-//                     fJavaLength= 0;
-//             }
-       }
-
-       /*
-        * @see ITokenScanner#setRange(IDocument, int, int)
-        */
-       public void setRange(IDocument document, int offset, int length) {
-
-               fScanner.setRange(document, offset, length);
-               fTokenOffset= offset;
-               fTokenLength= 0;                
-               fPrefixLength= 0;
-               fLast= NONE;
-               fState= HTML;
-
-               // emulate JavaPartitionScanner
-//             if (fgEmulate) {
-//                     fJavaOffset= -1;
-//                     fJavaLength= 0;
-//             }
-       }
-
-       /*
-        * @see ITokenScanner#getTokenLength()
-        */
-       public int getTokenLength() {
-               return fTokenLength;
-       }
-
-       /*
-        * @see ITokenScanner#getTokenOffset()
-        */
-       public int getTokenOffset() {
-               return fTokenOffset;
-       }
-
-}
+public class FastJavaPartitionScanner implements IPartitionTokenScanner, IPHPPartitions {
+
+  // states
+  private static final int PHP = 0;
+
+  private static final int SINGLE_LINE_COMMENT = 1;
+
+  private static final int MULTI_LINE_COMMENT = 2;
+
+  private static final int PHPDOC = 3;
+
+  private static final int STRING_DQ = 4;
+
+  private static final int STRING_SQ = 5;
+
+  //   private static final int CHARACTER= 4;
+
+  // beginning of prefixes and postfixes
+  private static final int NONE = 0;
+
+  private static final int BACKSLASH = 1; // postfix for STRING and CHARACTER
+
+  private static final int SLASH = 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
+
+  private static final int SLASH_STAR = 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
+
+  private static final int SLASH_STAR_STAR = 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
+
+  private static final int STAR = 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
+
+  private static final int CARRIAGE_RETURN = 6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
+
+  /** The scanner. */
+  private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(1000); // faster implementation
+
+  /** The offset of the last returned token. */
+  private int fTokenOffset;
+
+  /** The length of the last returned token. */
+  private int fTokenLength;
+
+  /** The state of the scanner. */
+  private int fState;
+
+  /** The last significant characters read. */
+  private int fLast;
+
+  /** The amount of characters already read on first call to nextToken(). */
+  private int fPrefixLength;
+
+  // emulate JavaPartitionScanner
+  private boolean fEmulate = false;
+
+  private int fJavaOffset;
+
+  private int fJavaLength;
+
+  private final IToken[] fTokens = new IToken[] { new Token(null), new Token(PHP_SINGLELINE_COMMENT),
+      new Token(PHP_MULTILINE_COMMENT), new Token(PHP_PHPDOC_COMMENT), new Token(PHP_STRING_DQ), new Token(PHP_STRING_SQ) };
+
+  public FastJavaPartitionScanner(boolean emulate) {
+    fEmulate = emulate;
+  }
+
+  public FastJavaPartitionScanner() {
+    this(false);
+  }
+
+  /*
+   * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+   */
+  public IToken nextToken() {
+
+    // emulate JavaPartitionScanner
+    if (fEmulate) {
+      if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
+        fTokenOffset += fTokenLength;
+        return fTokens[PHP];
+      } else {
+        fJavaOffset = -1;
+        fJavaLength = 0;
+      }
+    }
+
+    fTokenOffset += fTokenLength;
+    fTokenLength = fPrefixLength;
+
+    while (true) {
+      final int ch = fScanner.read();
+
+      // characters
+      switch (ch) {
+      case ICharacterScanner.EOF:
+        if (fTokenLength > 0) {
+          fLast = NONE; // ignore last
+          return preFix(fState, PHP, NONE, 0);
+
+        } else {
+          fLast = NONE;
+          fPrefixLength = 0;
+          return Token.EOF;
+        }
+
+      case '\r':
+        // emulate JavaPartitionScanner
+        if (!fEmulate && fLast != CARRIAGE_RETURN) {
+          fLast = CARRIAGE_RETURN;
+          fTokenLength++;
+          continue;
+
+        } else {
+
+          switch (fState) {
+          case SINGLE_LINE_COMMENT:
+            //                                 case CHARACTER:
+            //                                 case STRING_DQ:
+            //                                 case STRING_SQ:
+            if (fTokenLength > 0) {
+              IToken token = fTokens[fState];
+
+              // emulate JavaPartitionScanner
+              if (fEmulate) {
+                fTokenLength++;
+                fLast = NONE;
+                fPrefixLength = 0;
+              } else {
+                fLast = CARRIAGE_RETURN;
+                fPrefixLength = 1;
+              }
+
+              fState = PHP;
+              return token;
+
+            } else {
+              consume();
+              continue;
+            }
+
+          default:
+            consume();
+            continue;
+          }
+        }
+
+      case '\n':
+        switch (fState) {
+        case SINGLE_LINE_COMMENT:
+          //                           case CHARACTER:
+          //                           case STRING_DQ:
+          //                           case STRING_SQ:
+          // assert(fTokenLength > 0);
+          return postFix(fState);
+
+        default:
+          consume();
+          continue;
+        }
+
+      default:
+        if (!fEmulate && fLast == CARRIAGE_RETURN) {
+          switch (fState) {
+          case SINGLE_LINE_COMMENT:
+            //                                 case CHARACTER:
+            //                                 case STRING_DQ:
+            //                                 case STRING_SQ:
+            int last;
+            int newState;
+            switch (ch) {
+            case '/':
+              last = SLASH;
+              newState = PHP;
+              break;
+
+            case '*':
+              last = STAR;
+              newState = PHP;
+              break;
+
+            case '\'':
+              last = NONE;
+              newState = STRING_SQ;
+              break;
+
+            case '"':
+              last = NONE;
+              newState = STRING_DQ;
+              break;
+
+            case '\r':
+              last = CARRIAGE_RETURN;
+              newState = PHP;
+              break;
+
+            case '\\':
+              last = BACKSLASH;
+              newState = PHP;
+              break;
+
+            default:
+              last = NONE;
+              newState = PHP;
+              break;
+            }
+
+            fLast = NONE; // ignore fLast
+            return preFix(fState, newState, last, 1);
+
+          default:
+            break;
+          }
+        }
+      }
+
+      // states
+      switch (fState) {
+      case PHP:
+        switch (ch) {
+        case '#':
+          if (fTokenLength > 0) {
+            return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
+          } else {
+            preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
+            fTokenOffset += fTokenLength;
+            fTokenLength = fPrefixLength;
+            break;
+          }
+        case '/':
+          if (fLast == SLASH) {
+            if (fTokenLength - getLastLength(fLast) > 0) {
+              return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
+            } else {
+              preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
+              fTokenOffset += fTokenLength;
+              fTokenLength = fPrefixLength;
+              break;
+            }
+
+          } else {
+            fTokenLength++;
+            fLast = SLASH;
+            break;
+          }
+
+        case '*':
+          if (fLast == SLASH) {
+            if (fTokenLength - getLastLength(fLast) > 0)
+              return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
+            else {
+              preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
+              fTokenOffset += fTokenLength;
+              fTokenLength = fPrefixLength;
+              break;
+            }
+
+          } else {
+            consume();
+            break;
+          }
+
+        case '\'':
+          fLast = NONE; // ignore fLast
+          if (fTokenLength > 0)
+            return preFix(PHP, STRING_SQ, NONE, 1);
+          else {
+            preFix(PHP, STRING_SQ, NONE, 1);
+            fTokenOffset += fTokenLength;
+            fTokenLength = fPrefixLength;
+            break;
+          }
+
+        case '"':
+          fLast = NONE; // ignore fLast
+          if (fTokenLength > 0)
+            return preFix(PHP, STRING_DQ, NONE, 1);
+          else {
+            preFix(PHP, STRING_DQ, NONE, 1);
+            fTokenOffset += fTokenLength;
+            fTokenLength = fPrefixLength;
+            break;
+          }
+
+        default:
+          consume();
+          break;
+        }
+        break;
+
+      case SINGLE_LINE_COMMENT:
+        consume();
+        break;
+
+      case PHPDOC:
+        switch (ch) {
+        case '/':
+          switch (fLast) {
+          case SLASH_STAR_STAR:
+            return postFix(MULTI_LINE_COMMENT);
+
+          case STAR:
+            return postFix(PHPDOC);
+
+          default:
+            consume();
+            break;
+          }
+          break;
+
+        case '*':
+          fTokenLength++;
+          fLast = STAR;
+          break;
+
+        default:
+          consume();
+          break;
+        }
+        break;
+
+      case MULTI_LINE_COMMENT:
+        switch (ch) {
+        case '*':
+          if (fLast == SLASH_STAR) {
+            fLast = SLASH_STAR_STAR;
+            fTokenLength++;
+            fState = PHPDOC;
+          } else {
+            fTokenLength++;
+            fLast = STAR;
+          }
+          break;
+
+        case '/':
+          if (fLast == STAR) {
+            return postFix(MULTI_LINE_COMMENT);
+          } else {
+            consume();
+            break;
+          }
+
+        default:
+          consume();
+          break;
+        }
+        break;
+
+      case STRING_DQ:
+        switch (ch) {
+        case '\\':
+          fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
+          fTokenLength++;
+          break;
+
+        case '\"':
+          if (fLast != BACKSLASH) {
+            return postFix(STRING_DQ);
+
+          } else {
+            consume();
+            break;
+          }
+
+        default:
+          consume();
+          break;
+        }
+        break;
+      case STRING_SQ:
+        switch (ch) {
+        case '\\':
+          fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
+          fTokenLength++;
+          break;
+
+        case '\'':
+          if (fLast != BACKSLASH) {
+            return postFix(STRING_SQ);
+
+          } else {
+            consume();
+            break;
+          }
+
+        default:
+          consume();
+          break;
+        }
+        break;
+      //                       case CHARACTER:
+      //                               switch (ch) {
+      //                               case '\\':
+      //                                       fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
+      //                                       fTokenLength++;
+      //                                       break;
+      //       
+      //                               case '\'':
+      //                                       if (fLast != BACKSLASH) {
+      //                                               return postFix(CHARACTER);
+      //       
+      //                                       } else {
+      //                                               consume();
+      //                                               break;
+      //                                       }
+      //       
+      //                               default:
+      //                                       consume();
+      //                                       break;
+      //                               }
+      //                               break;
+      }
+    }
+  }
+
+  private static final int getLastLength(int last) {
+    switch (last) {
+    default:
+      return -1;
+
+    case NONE:
+      return 0;
+
+    case CARRIAGE_RETURN:
+    case BACKSLASH:
+    case SLASH:
+    case STAR:
+      return 1;
+
+    case SLASH_STAR:
+      return 2;
+
+    case SLASH_STAR_STAR:
+      return 3;
+    }
+  }
+
+  private final void consume() {
+    fTokenLength++;
+    fLast = NONE;
+  }
+
+  private final IToken postFix(int state) {
+    fTokenLength++;
+    fLast = NONE;
+    fState = PHP;
+    fPrefixLength = 0;
+    return fTokens[state];
+  }
+
+  private final IToken preFix(int state, int newState, int last, int prefixLength) {
+    // emulate JavaPartitionScanner
+    if (fEmulate && state == PHP && (fTokenLength - getLastLength(fLast) > 0)) {
+      fTokenLength -= getLastLength(fLast);
+      fJavaOffset = fTokenOffset;
+      fJavaLength = fTokenLength;
+      fTokenLength = 1;
+      fState = newState;
+      fPrefixLength = prefixLength;
+      fLast = last;
+      return fTokens[state];
+
+    } else {
+      fTokenLength -= getLastLength(fLast);
+      fLast = last;
+      fPrefixLength = prefixLength;
+      IToken token = fTokens[state];
+      fState = newState;
+      return token;
+    }
+  }
+
+  private static int getState(String contentType) {
+
+    if (contentType == null)
+      return PHP;
+
+    else if (contentType.equals(PHP_SINGLELINE_COMMENT))
+      return SINGLE_LINE_COMMENT;
+
+    else if (contentType.equals(PHP_MULTILINE_COMMENT))
+      return MULTI_LINE_COMMENT;
+
+    else if (contentType.equals(PHP_PHPDOC_COMMENT))
+      return PHPDOC;
+
+    else if (contentType.equals(PHP_STRING_DQ))
+      return STRING_DQ;
+    else if (contentType.equals(PHP_STRING_SQ))
+      return STRING_SQ;
+    //         else if (contentType.equals(JAVA_CHARACTER))
+    //                 return CHARACTER;
+
+    else
+      return PHP;
+  }
+
+  /*
+   * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
+   */
+  public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
+    fScanner.setRange(document, offset, length);
+    setRange(document, offset, length);
+    fTokenOffset = partitionOffset;
+    fTokenLength = 0;
+    fPrefixLength = offset - partitionOffset;
+    fLast = NONE;
+
+    if (offset == partitionOffset) {
+      // restart at beginning of partition
+      fState = PHP;
+    } else {
+      fState = getState(contentType);
+    }
+
+    // emulate JavaPartitionScanner
+    if (fEmulate) {
+      fJavaOffset = -1;
+      fJavaLength = 0;
+    }
+  }
+
+  /*
+   * @see ITokenScanner#setRange(IDocument, int, int)
+   */
+  public void setRange(IDocument document, int offset, int length) {
+    fScanner.setRange(document, offset, length);
+    fTokenOffset = offset;
+    fTokenLength = 0;
+    fPrefixLength = 0;
+    fLast = NONE;
+    fState = PHP;
+
+    // emulate JavaPartitionScanner
+    if (fEmulate) {
+      fJavaOffset = -1;
+      fJavaLength = 0;
+    }
+  }
+
+  /*
+   * @see ITokenScanner#getTokenLength()
+   */
+  public int getTokenLength() {
+    return fTokenLength;
+  }
+
+  /*
+   * @see ITokenScanner#getTokenOffset()
+   */
+  public int getTokenOffset() {
+    if (AbstractPartitioner.DEBUG) {
+      Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));
+    }
+    return fTokenOffset;
+  }
+
+}
\ No newline at end of file