2  * Copyright (c) 2002-2004 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://www.eclipse.org/legal/cpl-v10.html
 
   9  *     Igor Malinin - initial contribution
 
  11  * $Id: PHPXMLPartitionScanner.java,v 1.3 2006-10-21 23:14:13 pombredanne Exp $
 
  14 package net.sourceforge.phpeclipse.xml.ui.internal.text;
 
  16 import java.util.HashMap;
 
  19 import org.eclipse.jface.text.Assert;
 
  20 import org.eclipse.jface.text.BadLocationException;
 
  21 import org.eclipse.jface.text.IDocument;
 
  22 import org.eclipse.jface.text.rules.ICharacterScanner;
 
  23 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 
  24 import org.eclipse.jface.text.rules.IToken;
 
  25 import org.eclipse.jface.text.rules.Token;
 
  30  * @author Igor Malinin
 
  32 public class PHPXMLPartitionScanner implements IPartitionTokenScanner {
 
  33         // public static final String XML_PI = "__xml_processing_instruction";
 
  34         public static final String XML_COMMENT = "__xml_comment";
 
  36         public static final String XML_DECL = "__xml_declaration";
 
  38         public static final String XML_TAG = "__xml_tag";
 
  40         public static final String XML_ATTRIBUTE = "__xml_attribute";
 
  42         public static final String XML_CDATA = "__xml_cdata";
 
  44         public static final String DTD_INTERNAL = "__dtd_internal";
 
  46         // public static final String DTD_INTERNAL_PI = "__dtd_internal_pi";
 
  47         public static final String DTD_INTERNAL_COMMENT = "__dtd_internal_comment";
 
  49         public static final String DTD_INTERNAL_DECL = "__dtd_internal_declaration";
 
  51         public static final String DTD_CONDITIONAL = "__dtd_conditional";
 
  53         public static final int STATE_DEFAULT = 0;
 
  55         public static final int STATE_TAG = 1;
 
  57         public static final int STATE_DECL = 2;
 
  59         public static final int STATE_CDATA = 4;
 
  61         public static final int STATE_INTERNAL = 8;
 
  63         protected IDocument document;
 
  71         protected int position;
 
  75         protected boolean parsedtd;
 
  77         protected Map tokens = new HashMap();
 
  79         public PHPXMLPartitionScanner(boolean parsedtd) {
 
  80                 this.parsedtd = parsedtd;
 
  84          * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
 
  86         public IToken nextToken() {
 
  91                         return nextTagToken();
 
  94                         return nextDeclToken();
 
  97                         return nextCDATAToken();
 
 101                 case ICharacterScanner.EOF:
 
 102                         state = STATE_DEFAULT;
 
 103                         return getToken(null);
 
 107                         case ICharacterScanner.EOF:
 
 108                                 if (parsedtd || isInternal()) {
 
 112                                 state = STATE_DEFAULT;
 
 113                                 return getToken(XML_TAG);
 
 118                         // return nextPIToken();
 
 120                         case '!': // <! <!DEFINITION or <![CDATA[ or <!--COMMENT
 
 122                                 case ICharacterScanner.EOF:
 
 123                                         state = STATE_DEFAULT;
 
 124                                         return getToken(XML_TAG);
 
 126                                 case '-': // <!- <!--COMMENT
 
 128                                         case ICharacterScanner.EOF:
 
 129                                                 return nextDeclToken();
 
 132                                                 return nextCommentToken();
 
 135                                 case '[': // <![ <![CDATA[ or <![%cond;[
 
 137                                                 return nextConditionalToken();
 
 141                                                 return nextCDATAToken();
 
 145                                 return nextDeclToken();
 
 148                         if (parsedtd || isInternal()) {
 
 154                         return nextTagToken();
 
 171                         case ICharacterScanner.EOF:
 
 172                                 state = STATE_DEFAULT;
 
 173                                 return getToken(null);
 
 176                                 if (parsedtd || isInternal()) {
 
 178                                         case ICharacterScanner.EOF:
 
 179                                                 state = STATE_DEFAULT;
 
 180                                                 return getToken(null);
 
 194                                 state &= STATE_INTERNAL;
 
 195                                 return getToken(isInternal() ? DTD_INTERNAL : null);
 
 202                                         if (position == offset) {
 
 208                                         return getToken(DTD_INTERNAL);
 
 214         private IToken nextTagToken() {
 
 218                 case ICharacterScanner.EOF:
 
 220                         state = STATE_DEFAULT;
 
 221                         return getToken(XML_TAG);
 
 230                                         return getToken(XML_ATTRIBUTE);
 
 237                                 case ICharacterScanner.EOF:
 
 238                                         state = STATE_DEFAULT;
 
 239                                         return getToken(XML_ATTRIBUTE);
 
 251                         case ICharacterScanner.EOF:
 
 253                                 state = STATE_DEFAULT;
 
 254                                 return getToken(XML_TAG);
 
 261                                 return getToken(XML_TAG);
 
 266         private IToken nextDeclToken() {
 
 269                         case ICharacterScanner.EOF:
 
 270                                 state = STATE_DEFAULT;
 
 271                                 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
 
 274                                 if (parsedtd || isInternal()) {
 
 276                                         case ICharacterScanner.EOF:
 
 277                                                 state = STATE_DEFAULT;
 
 278                                                 return getToken(isInternal() ? DTD_INTERNAL : null);
 
 293                                 state &= STATE_INTERNAL;
 
 294                                 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
 
 296                         case '[': // <!DOCTYPE xxx [dtd]>
 
 298                                         state = STATE_INTERNAL;
 
 299                                         return getToken(XML_DECL);
 
 305         private IToken nextCommentToken() {
 
 306                 state &= STATE_INTERNAL;
 
 310                         case ICharacterScanner.EOF:
 
 315                                 case ICharacterScanner.EOF:
 
 320                                         case ICharacterScanner.EOF:
 
 331                 return getToken(isInternal() ? DTD_INTERNAL_COMMENT : XML_COMMENT);
 
 334         private IToken nextCDATAToken() {
 
 335                 state = STATE_DEFAULT;
 
 339                         case ICharacterScanner.EOF:
 
 344                                 case ICharacterScanner.EOF:
 
 349                                         case ICharacterScanner.EOF:
 
 361                 return getToken(XML_CDATA);
 
 364         private IToken nextConditionalToken() {
 
 365                 state = STATE_DEFAULT;
 
 371                         case ICharacterScanner.EOF:
 
 376                                 case ICharacterScanner.EOF:
 
 381                                         case ICharacterScanner.EOF:
 
 398                                 case ICharacterScanner.EOF:
 
 403                                         case ICharacterScanner.EOF:
 
 419                 return getToken(DTD_CONDITIONAL);
 
 422         private IToken getToken(String type) {
 
 423                 length = position - offset;
 
 430                         return Token.UNDEFINED;
 
 433                 IToken token = (IToken) tokens.get(type);
 
 435                         token = new Token(type);
 
 436                         tokens.put(type, token);
 
 442         private boolean isInternal() {
 
 443                 return (state & STATE_INTERNAL) != 0;
 
 447                 if (position >= end) {
 
 448                         return ICharacterScanner.EOF;
 
 452                         return document.getChar(position++);
 
 453                 } catch (BadLocationException e) {
 
 455                         return ICharacterScanner.EOF;
 
 459         private void unread() {
 
 464          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
 
 466         public int getTokenOffset() {
 
 467                 Assert.isTrue(offset >= 0, Integer.toString(offset));
 
 472          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
 
 474         public int getTokenLength() {
 
 479          * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
 
 482         public void setRange(IDocument document, int offset, int length) {
 
 483                 this.document = document;
 
 484                 this.end = offset + length;
 
 486                 this.offset = offset;
 
 487                 this.position = offset;
 
 490                 this.state = STATE_DEFAULT;
 
 494          * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
 
 496         // public void setPartialRange(IDocument document, int offset, int length,
 
 497         // String contentType, int partitionOffset) {
 
 498         // state = STATE_DEFAULT;
 
 499         // if (partitionOffset > -1) {
 
 500         // int delta = offset - partitionOffset;
 
 502         // setRange(document, partitionOffset, length + delta);
 
 506         // setRange(document, partitionOffset, length);
 
 509          * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
 
 511         public void setPartialRange(IDocument document, int offset, int length,
 
 512                         String contentType, int partitionOffset) {
 
 513                 // boolean flag = false;
 
 514                 this.document = document;
 
 515                 this.end = offset + length;
 
 517                 // NB! Undocumented value: -1
 
 518                 if (partitionOffset >= 0) {
 
 519                         offset = partitionOffset;
 
 523                 this.offset = offset;
 
 524                 this.position = offset;
 
 528                 // state = STATE_DEFAULT;
 
 531                 if (contentType == XML_ATTRIBUTE) {
 
 536                 if (contentType == XML_TAG) {
 
 537                         state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
 
 541                 if (contentType == XML_DECL) {
 
 542                         state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
 
 546                 if (contentType == DTD_INTERNAL || contentType == DTD_INTERNAL_DECL
 
 547                                 || contentType == DTD_INTERNAL_COMMENT) {
 
 548                         state = STATE_INTERNAL;
 
 552                 state = STATE_DEFAULT;
 
 555         private boolean isContinuationPartition() {
 
 557                         String type = document.getContentType(offset - 1);
 
 559                         if (type != IDocument.DEFAULT_CONTENT_TYPE) {
 
 562                 } catch (BadLocationException e) {