1 /**********************************************************************
 
   2  Copyright (c) 2002  Widespace, OU  and others.
 
   3  All rights reserved.   This program and the accompanying materials
 
   4  are made available under the terms of the Common Public License v1.0
 
   5  which accompanies this distribution, and is available at
 
   6  http://solareclipse.sourceforge.net/legal/cpl-v10.html
 
   9  Igor Malinin - initial contribution
 
  11  $Id: PHPPartitionScanner.java,v 1.35 2007-03-17 14:07:31 axelcl Exp $
 
  12  **********************************************************************/
 
  13 package net.sourceforge.phpeclipse.phpeditor.php;
 
  15 import java.util.HashMap;
 
  18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
 
  19 import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
 
  22 //import org.eclipse.jface.text.Assert;
 
  23 import org.eclipse.core.runtime.Assert;
 
  24 import org.eclipse.jface.text.BadLocationException;
 
  25 import org.eclipse.jface.text.IDocument;
 
  26 import org.eclipse.jface.text.rules.ICharacterScanner;
 
  27 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 
  28 import org.eclipse.jface.text.rules.IToken;
 
  29 import org.eclipse.jface.text.rules.Token;
 
  34  * @author Igor Malinin
 
  36 public class PHPPartitionScanner implements IPartitionTokenScanner {
 
  37         public static final String PHP_SCRIPTING_AREA = "__php_scripting_area ";
 
  39         public static final int STATE_DEFAULT = 0;
 
  41         // public static final int STATE_TAG = 1;
 
  42         // public static final int STATE_SCRIPT = 2;
 
  44         private IDocument document;
 
  58         private Map tokens = new HashMap();
 
  60         public PHPPartitionScanner() {
 
  64          * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
 
  66         public IToken nextToken() {
 
  70                  * switch (state) { case STATE_TAG: return nextTagToken(); }
 
  74                 case ICharacterScanner.EOF:
 
  75                         // state = STATE_DEFAULT;
 
  76                         return getToken(null);
 
  80                         case ICharacterScanner.EOF:
 
  81                                 // state = STATE_DEFAULT;
 
  82                                 return getToken(null);
 
  88                                 // case ICharacterScanner.EOF:
 
  89                                 // state = STATE_DEFAULT;
 
  90                                 // return getToken(PHP_SCRIPTING_AREA);
 
  92                                 return scanUntilPHPEndToken(PHP_SCRIPTING_AREA);
 
 100                         case ICharacterScanner.EOF:
 
 101                                 // state = STATE_DEFAULT;
 
 102                                 return getToken(null);
 
 106                                 case ICharacterScanner.EOF:
 
 107                                         // state = STATE_DEFAULT;
 
 108                                         return getToken(null);
 
 123                                 // state = STATE_DEFAULT;
 
 124                                 return getToken(null);
 
 129         private IToken scanUntilPHPEndToken(String token) {
 
 133                         case ICharacterScanner.EOF:
 
 134                                 // state = STATE_DEFAULT;
 
 135                                 return getToken(token);
 
 136                         case '"': // double quoted string
 
 137                                 // read until end of double quoted string
 
 138                                 if (!readUntilEscapedDQ()) {
 
 139                                         // state = STATE_DEFAULT;
 
 140                                         return getToken(token);
 
 143                         case '<': // heredoc string
 
 146                                 case ICharacterScanner.EOF:
 
 151                                         case ICharacterScanner.EOF:
 
 154                                                 // read until end of heredoc string
 
 155                                                 if (!readUntilEscapedHEREDOC()) {
 
 156                                                         // state = STATE_DEFAULT;
 
 157                                                         return getToken(token);
 
 162                         case '\'': // single quoted string
 
 163                                 // read until end of single quoted string
 
 164                                 if (!readUntilEscapedSQ()) {
 
 165                                         // state = STATE_DEFAULT;
 
 166                                         return getToken(token);
 
 169                         case '/': // comment start?
 
 172                                 case ICharacterScanner.EOF:
 
 175                                         // read until end of line
 
 176                                         if (!readSingleLine()) {
 
 177                                                 // state = STATE_DEFAULT;
 
 178                                                 return getToken(token);
 
 182                                         // read until end of comment
 
 183                                         if (!readMultiLineComment()) {
 
 184                                                 // state = STATE_DEFAULT;
 
 185                                                 return getToken(token);
 
 192                         case '#': // line comment
 
 193                                 // read until end of line
 
 194                                 if (!readSingleLine()) {
 
 195                                         // state = STATE_DEFAULT;
 
 196                                         return getToken(token);
 
 202                                 case ICharacterScanner.EOF:
 
 204                                         // state = STATE_DEFAULT;
 
 205                                         return getToken(token);
 
 218         private IToken getToken(String type) {
 
 219                 length = position - offset;
 
 227                 // System.out.println("Length<0:"+document.get(offset,5)+""+length);
 
 228                 // } catch (BadLocationException e) {
 
 229                 // e.printStackTrace();
 
 234                         return Token.UNDEFINED;
 
 237                 IToken token = (IToken) tokens.get(type);
 
 239                         token = new Token(type);
 
 240                         tokens.put(type, token);
 
 247                 if (position >= end) {
 
 248                         return ICharacterScanner.EOF;
 
 252                         return document.getChar(position++);
 
 253                 } catch (BadLocationException e) {
 
 255                         return ICharacterScanner.EOF;
 
 259         private boolean readUntilEscapedDQ() {
 
 260                 // search last double quoted character
 
 264                                 if (position >= end) {
 
 267                                 ch = document.getChar(position++);
 
 269                                         if (position >= end) {
 
 272                                         ch = document.getChar(position++); // ignore escaped
 
 274                                 } else if (ch == '"') {
 
 278                 } catch (BadLocationException e) {
 
 284         private boolean readUntilEscapedSQ() {
 
 285                 // search last single quoted character
 
 289                                 if (position >= end) {
 
 292                                 ch = document.getChar(position++);
 
 294                                         if (position >= end) {
 
 297                                         ch = document.getChar(position++); // ignore escaped
 
 299                                 } else if (ch == '\'') {
 
 303                 } catch (BadLocationException e) {
 
 309         private boolean readUntilEscapedHEREDOC() {
 
 310                 // search until heredoc ends
 
 313                         StringBuffer buf = new StringBuffer();
 
 315                         if (position >= end) {
 
 318                         ch = document.getChar(position++);
 
 321                                 if (position >= end) {
 
 324                                 ch = document.getChar(position++);
 
 327                         if (!Scanner.isPHPIdentifierStart(ch)) {
 
 330                         while (Scanner.isPHPIdentifierPart(ch)) {
 
 332                                 if (position >= end) {
 
 335                                 ch = document.getChar(position++);
 
 337                         heredocIdent = buf.toString().toCharArray();
 
 339                                 if (position >= end) {
 
 342                                 ch = document.getChar(position++);
 
 343                                 if (ch == '\n') { // heredoc could end after a newline
 
 346                                                 if (position >= end) {
 
 349                                                 if (pos == heredocIdent.length) {
 
 352                                                 ch = document.getChar(position++); // ignore escaped
 
 354                                                 if (ch != heredocIdent[pos]) {
 
 361                 } catch (BadLocationException e) {
 
 367         private boolean readSingleLine() {
 
 370                                 if (position >= end) {
 
 373                         } while (document.getChar(position++) != '\n');
 
 375                 } catch (BadLocationException e) {
 
 381         private boolean readMultiLineComment() {
 
 385                                 if (position >= end) {
 
 388                                 ch = document.getChar(position++);
 
 390                                         if (position >= end) {
 
 393                                         if (document.getChar(position) == '/') {
 
 399                 } catch (BadLocationException e) {
 
 405         private void unread() {
 
 410          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
 
 412         public int getTokenOffset() {
 
 413                 if (AbstractPartitioner.DEBUG) {
 
 414                         Assert.isTrue(offset >= 0, Integer.toString(offset));
 
 420          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
 
 422         public int getTokenLength() {
 
 427          * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
 
 430         public void setRange(IDocument document, int offset, int length) {
 
 431                 this.document = document;
 
 432                 // this.begin = offset;
 
 433                 this.end = offset + length;
 
 435                 this.offset = offset;
 
 436                 this.position = offset;
 
 441          * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
 
 443         public void setPartialRange(IDocument document, int offset, int length,
 
 444                         String contentType, int partitionOffset) {
 
 445                 // state = STATE_DEFAULT;
 
 446                 if (partitionOffset > -1) {
 
 447                         int delta = offset - partitionOffset;
 
 449                                 setRange(document, partitionOffset, length + delta);
 
 453                 setRange(document, partitionOffset, length);
 
 456         // private boolean isContinuationPartition(IDocument document, int offset) {
 
 458         // String type = document.getContentType(offset - 1);
 
 460         // if (type != IDocument.DEFAULT_CONTENT_TYPE) {
 
 463         // } catch (BadLocationException e) {}