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;
 
  20 //import org.eclipse.jface.text.Assert;
 
  21 import org.eclipse.core.runtime.Assert;
 
  22 import org.eclipse.jface.text.BadLocationException;
 
  23 import org.eclipse.jface.text.IDocument;
 
  24 import org.eclipse.jface.text.rules.ICharacterScanner;
 
  25 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 
  26 import org.eclipse.jface.text.rules.IToken;
 
  27 import org.eclipse.jface.text.rules.Token;
 
  32  * @author Igor Malinin
 
  34 public class PHPXMLPartitionScanner implements IPartitionTokenScanner {
 
  35         // public static final String XML_PI = "__xml_processing_instruction";
 
  36         public static final String XML_COMMENT = "__xml_comment";
 
  38         public static final String XML_DECL = "__xml_declaration";
 
  40         public static final String XML_TAG = "__xml_tag";
 
  42         public static final String XML_ATTRIBUTE = "__xml_attribute";
 
  44         public static final String XML_CDATA = "__xml_cdata";
 
  46         public static final String DTD_INTERNAL = "__dtd_internal";
 
  48         // public static final String DTD_INTERNAL_PI = "__dtd_internal_pi";
 
  49         public static final String DTD_INTERNAL_COMMENT = "__dtd_internal_comment";
 
  51         public static final String DTD_INTERNAL_DECL = "__dtd_internal_declaration";
 
  53         public static final String DTD_CONDITIONAL = "__dtd_conditional";
 
  55         public static final int STATE_DEFAULT = 0;
 
  57         public static final int STATE_TAG = 1;
 
  59         public static final int STATE_DECL = 2;
 
  61         public static final int STATE_CDATA = 4;
 
  63         public static final int STATE_INTERNAL = 8;
 
  65         protected IDocument document;
 
  73         protected int position;
 
  77         protected boolean parsedtd;
 
  79         protected Map tokens = new HashMap();
 
  81         public PHPXMLPartitionScanner(boolean parsedtd) {
 
  82                 this.parsedtd = parsedtd;
 
  86          * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
 
  88         public IToken nextToken() {
 
  93                         return nextTagToken();
 
  96                         return nextDeclToken();
 
  99                         return nextCDATAToken();
 
 103                 case ICharacterScanner.EOF:
 
 104                         state = STATE_DEFAULT;
 
 105                         return getToken(null);
 
 109                         case ICharacterScanner.EOF:
 
 110                                 if (parsedtd || isInternal()) {
 
 114                                 state = STATE_DEFAULT;
 
 115                                 return getToken(XML_TAG);
 
 120                         // return nextPIToken();
 
 122                         case '!': // <! <!DEFINITION or <![CDATA[ or <!--COMMENT
 
 124                                 case ICharacterScanner.EOF:
 
 125                                         state = STATE_DEFAULT;
 
 126                                         return getToken(XML_TAG);
 
 128                                 case '-': // <!- <!--COMMENT
 
 130                                         case ICharacterScanner.EOF:
 
 131                                                 return nextDeclToken();
 
 134                                                 return nextCommentToken();
 
 137                                 case '[': // <![ <![CDATA[ or <![%cond;[
 
 139                                                 return nextConditionalToken();
 
 143                                                 return nextCDATAToken();
 
 147                                 return nextDeclToken();
 
 150                         if (parsedtd || isInternal()) {
 
 156                         return nextTagToken();
 
 173                         case ICharacterScanner.EOF:
 
 174                                 state = STATE_DEFAULT;
 
 175                                 return getToken(null);
 
 178                                 if (parsedtd || isInternal()) {
 
 180                                         case ICharacterScanner.EOF:
 
 181                                                 state = STATE_DEFAULT;
 
 182                                                 return getToken(null);
 
 196                                 state &= STATE_INTERNAL;
 
 197                                 return getToken(isInternal() ? DTD_INTERNAL : null);
 
 204                                         if (position == offset) {
 
 210                                         return getToken(DTD_INTERNAL);
 
 216         private IToken nextTagToken() {
 
 220                 case ICharacterScanner.EOF:
 
 222                         state = STATE_DEFAULT;
 
 223                         return getToken(XML_TAG);
 
 232                                         return getToken(XML_ATTRIBUTE);
 
 239                                 case ICharacterScanner.EOF:
 
 240                                         state = STATE_DEFAULT;
 
 241                                         return getToken(XML_ATTRIBUTE);
 
 253                         case ICharacterScanner.EOF:
 
 255                                 state = STATE_DEFAULT;
 
 256                                 return getToken(XML_TAG);
 
 263                                 return getToken(XML_TAG);
 
 268         private IToken nextDeclToken() {
 
 271                         case ICharacterScanner.EOF:
 
 272                                 state = STATE_DEFAULT;
 
 273                                 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
 
 276                                 if (parsedtd || isInternal()) {
 
 278                                         case ICharacterScanner.EOF:
 
 279                                                 state = STATE_DEFAULT;
 
 280                                                 return getToken(isInternal() ? DTD_INTERNAL : null);
 
 295                                 state &= STATE_INTERNAL;
 
 296                                 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
 
 298                         case '[': // <!DOCTYPE xxx [dtd]>
 
 300                                         state = STATE_INTERNAL;
 
 301                                         return getToken(XML_DECL);
 
 307         private IToken nextCommentToken() {
 
 308                 state &= STATE_INTERNAL;
 
 312                         case ICharacterScanner.EOF:
 
 317                                 case ICharacterScanner.EOF:
 
 322                                         case ICharacterScanner.EOF:
 
 333                 return getToken(isInternal() ? DTD_INTERNAL_COMMENT : XML_COMMENT);
 
 336         private IToken nextCDATAToken() {
 
 337                 state = STATE_DEFAULT;
 
 341                         case ICharacterScanner.EOF:
 
 346                                 case ICharacterScanner.EOF:
 
 351                                         case ICharacterScanner.EOF:
 
 363                 return getToken(XML_CDATA);
 
 366         private IToken nextConditionalToken() {
 
 367                 state = STATE_DEFAULT;
 
 373                         case ICharacterScanner.EOF:
 
 378                                 case ICharacterScanner.EOF:
 
 383                                         case ICharacterScanner.EOF:
 
 400                                 case ICharacterScanner.EOF:
 
 405                                         case ICharacterScanner.EOF:
 
 421                 return getToken(DTD_CONDITIONAL);
 
 424         private IToken getToken(String type) {
 
 425                 length = position - offset;
 
 432                         return Token.UNDEFINED;
 
 435                 IToken token = (IToken) tokens.get(type);
 
 437                         token = new Token(type);
 
 438                         tokens.put(type, token);
 
 444         private boolean isInternal() {
 
 445                 return (state & STATE_INTERNAL) != 0;
 
 449                 if (position >= end) {
 
 450                         return ICharacterScanner.EOF;
 
 454                         return document.getChar(position++);
 
 455                 } catch (BadLocationException e) {
 
 457                         return ICharacterScanner.EOF;
 
 461         private void unread() {
 
 466          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
 
 468         public int getTokenOffset() {
 
 469                 Assert.isTrue(offset >= 0, Integer.toString(offset));
 
 474          * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
 
 476         public int getTokenLength() {
 
 481          * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
 
 484         public void setRange(IDocument document, int offset, int length) {
 
 485                 this.document = document;
 
 486                 this.end = offset + length;
 
 488                 this.offset = offset;
 
 489                 this.position = offset;
 
 492                 this.state = STATE_DEFAULT;
 
 496          * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
 
 498         // public void setPartialRange(IDocument document, int offset, int length,
 
 499         // String contentType, int partitionOffset) {
 
 500         // state = STATE_DEFAULT;
 
 501         // if (partitionOffset > -1) {
 
 502         // int delta = offset - partitionOffset;
 
 504         // setRange(document, partitionOffset, length + delta);
 
 508         // setRange(document, partitionOffset, length);
 
 511          * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
 
 513         public void setPartialRange(IDocument document, int offset, int length,
 
 514                         String contentType, int partitionOffset) {
 
 515                 // boolean flag = false;
 
 516                 this.document = document;
 
 517                 this.end = offset + length;
 
 519                 // NB! Undocumented value: -1
 
 520                 if (partitionOffset >= 0) {
 
 521                         offset = partitionOffset;
 
 525                 this.offset = offset;
 
 526                 this.position = offset;
 
 530                 // state = STATE_DEFAULT;
 
 533                 if (contentType == XML_ATTRIBUTE) {
 
 538                 if (contentType == XML_TAG) {
 
 539                         state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
 
 543                 if (contentType == XML_DECL) {
 
 544                         state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
 
 548                 if (contentType == DTD_INTERNAL || contentType == DTD_INTERNAL_DECL
 
 549                                 || contentType == DTD_INTERNAL_COMMENT) {
 
 550                         state = STATE_INTERNAL;
 
 554                 state = STATE_DEFAULT;
 
 557         private boolean isContinuationPartition() {
 
 559                         String type = document.getContentType(offset - 1);
 
 561                         if (type != IDocument.DEFAULT_CONTENT_TYPE) {
 
 564                 } catch (BadLocationException e) {