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) {