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: XMLPartitionScanner.java,v 1.5 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 XMLPartitionScanner implements IPartitionTokenScanner {
35 public static final String XML_PI = "__xml_processing_instruction";
37 public static final String XML_COMMENT = "__xml_comment";
39 public static final String XML_DECL = "__xml_declaration";
41 public static final String XML_TAG = "__xml_tag";
43 public static final String XML_ATTRIBUTE = "__xml_attribute";
45 public static final String XML_CDATA = "__xml_cdata";
47 public static final String DTD_INTERNAL = "__dtd_internal";
49 public static final String DTD_INTERNAL_PI = "__dtd_internal_pi";
51 public static final String DTD_INTERNAL_COMMENT = "__dtd_internal_comment";
53 public static final String DTD_INTERNAL_DECL = "__dtd_internal_declaration";
55 public static final String DTD_CONDITIONAL = "__dtd_conditional";
57 public static final int STATE_DEFAULT = 0;
59 public static final int STATE_TAG = 1;
61 public static final int STATE_DECL = 2;
63 public static final int STATE_CDATA = 4;
65 public static final int STATE_INTERNAL = 8;
67 protected IDocument document;
75 protected int position;
79 protected boolean parsedtd;
81 protected Map tokens = new HashMap();
83 public XMLPartitionScanner(boolean parsedtd) {
84 this.parsedtd = parsedtd;
88 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
90 public IToken nextToken() {
95 return nextTagToken();
98 return nextDeclToken();
101 return nextCDATAToken();
105 case ICharacterScanner.EOF:
106 state = STATE_DEFAULT;
107 return getToken(null);
111 case ICharacterScanner.EOF:
112 if (parsedtd || isInternal()) {
116 state = STATE_DEFAULT;
117 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 nextPIToken() {
337 state &= STATE_INTERNAL;
341 case ICharacterScanner.EOF:
346 case ICharacterScanner.EOF:
355 return getToken(isInternal() ? DTD_INTERNAL_PI : XML_PI);
358 private IToken nextCDATAToken() {
359 state = STATE_DEFAULT;
363 case ICharacterScanner.EOF:
368 case ICharacterScanner.EOF:
373 case ICharacterScanner.EOF:
385 return getToken(XML_CDATA);
388 private IToken nextConditionalToken() {
389 state = STATE_DEFAULT;
395 case ICharacterScanner.EOF:
400 case ICharacterScanner.EOF:
405 case ICharacterScanner.EOF:
422 case ICharacterScanner.EOF:
427 case ICharacterScanner.EOF:
443 return getToken(DTD_CONDITIONAL);
446 private IToken getToken(String type) {
447 length = position - offset;
454 return Token.UNDEFINED;
457 IToken token = (IToken) tokens.get(type);
459 token = new Token(type);
460 tokens.put(type, token);
466 private boolean isInternal() {
467 return (state & STATE_INTERNAL) != 0;
471 if (position >= end) {
472 return ICharacterScanner.EOF;
476 return document.getChar(position++);
477 } catch (BadLocationException e) {
479 return ICharacterScanner.EOF;
483 private void unread() {
488 * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
490 public int getTokenOffset() {
491 Assert.isTrue(offset >= 0, Integer.toString(offset));
496 * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
498 public int getTokenLength() {
503 * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int,
506 public void setRange(IDocument document, int offset, int length) {
507 this.document = document;
508 this.end = offset + length;
510 this.offset = offset;
511 this.position = offset;
514 this.state = STATE_DEFAULT;
518 * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
520 // public void setPartialRange(IDocument document, int offset, int length,
521 // String contentType, int partitionOffset) {
522 // state = STATE_DEFAULT;
523 // if (partitionOffset > -1) {
524 // int delta = offset - partitionOffset;
526 // setRange(document, partitionOffset, length + delta);
530 // setRange(document, partitionOffset, length);
533 * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
535 public void setPartialRange(IDocument document, int offset, int length,
536 String contentType, int partitionOffset) {
537 // boolean flag = false;
538 this.document = document;
539 this.end = offset + length;
541 // NB! Undocumented value: -1
542 if (partitionOffset >= 0) {
543 offset = partitionOffset;
547 this.offset = offset;
548 this.position = offset;
552 // state = STATE_DEFAULT;
555 if (contentType == XML_ATTRIBUTE) {
560 if (contentType == XML_TAG) {
561 state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
565 if (contentType == XML_DECL) {
566 state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
570 if (contentType == DTD_INTERNAL || contentType == DTD_INTERNAL_PI
571 || contentType == DTD_INTERNAL_DECL
572 || contentType == DTD_INTERNAL_COMMENT) {
573 state = STATE_INTERNAL;
577 state = STATE_DEFAULT;
580 private boolean isContinuationPartition() {
582 String type = document.getContentType(offset - 1);
584 if (type != IDocument.DEFAULT_CONTENT_TYPE) {
587 } catch (BadLocationException e) {