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.3 2005-05-15 23:23:02 axelcl 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;
31 * @author Igor Malinin
33 public class XMLPartitionScanner implements IPartitionTokenScanner {
34 public static final String XML_PI = "__xml_processing_instruction";
35 public static final String XML_COMMENT = "__xml_comment";
36 public static final String XML_DECL = "__xml_declaration";
37 public static final String XML_TAG = "__xml_tag";
38 public static final String XML_ATTRIBUTE = "__xml_attribute";
39 public static final String XML_CDATA = "__xml_cdata";
41 public static final String DTD_INTERNAL = "__dtd_internal";
42 public static final String DTD_INTERNAL_PI = "__dtd_internal_pi";
43 public static final String DTD_INTERNAL_COMMENT = "__dtd_internal_comment";
44 public static final String DTD_INTERNAL_DECL = "__dtd_internal_declaration";
45 public static final String DTD_CONDITIONAL = "__dtd_conditional";
47 public static final int STATE_DEFAULT = 0;
48 public static final int STATE_TAG = 1;
49 public static final int STATE_DECL = 2;
50 public static final int STATE_CDATA = 4;
52 public static final int STATE_INTERNAL = 8;
54 protected IDocument document;
60 protected int position;
63 protected boolean parsedtd;
65 protected Map tokens = new HashMap();
67 public XMLPartitionScanner(boolean parsedtd) {
68 this.parsedtd = parsedtd;
72 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
74 public IToken nextToken() {
79 return nextTagToken();
82 return nextDeclToken();
85 return nextCDATAToken();
89 case ICharacterScanner.EOF:
90 state = STATE_DEFAULT;
91 return getToken(null);
95 case ICharacterScanner.EOF:
96 if (parsedtd || isInternal()) {
100 state = STATE_DEFAULT;
101 return getToken(XML_TAG);
104 return nextPIToken();
106 case '!': // <! <!DEFINITION or <![CDATA[ or <!--COMMENT
108 case ICharacterScanner.EOF:
109 state = STATE_DEFAULT;
110 return getToken(XML_TAG);
112 case '-': // <!- <!--COMMENT
114 case ICharacterScanner.EOF:
115 return nextDeclToken();
118 return nextCommentToken();
121 case '[': // <![ <![CDATA[ or <![%cond;[
123 return nextConditionalToken();
127 return nextCDATAToken();
131 return nextDeclToken();
134 if (parsedtd || isInternal()) {
140 return nextTagToken();
158 case ICharacterScanner.EOF:
159 state = STATE_DEFAULT;
160 return getToken(null);
163 if (parsedtd || isInternal()) {
165 case ICharacterScanner.EOF:
166 state = STATE_DEFAULT;
167 return getToken(null);
181 state &= STATE_INTERNAL;
182 return getToken(isInternal() ? DTD_INTERNAL : null);
189 if (position == offset) {
195 return getToken(DTD_INTERNAL);
201 private IToken nextTagToken() {
205 case ICharacterScanner.EOF:
207 state = STATE_DEFAULT;
208 return getToken(XML_TAG);
216 return getToken(XML_ATTRIBUTE);
223 case ICharacterScanner.EOF:
224 state = STATE_DEFAULT;
225 return getToken(XML_ATTRIBUTE);
237 case ICharacterScanner.EOF:
239 state = STATE_DEFAULT;
240 return getToken(XML_TAG);
246 return getToken(XML_TAG);
251 private IToken nextDeclToken() {
254 case ICharacterScanner.EOF:
255 state = STATE_DEFAULT;
256 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
259 if (parsedtd || isInternal()) {
261 case ICharacterScanner.EOF:
262 state = STATE_DEFAULT;
263 return getToken(isInternal() ? DTD_INTERNAL : null);
278 state &= STATE_INTERNAL;
279 return getToken(isInternal() ? DTD_INTERNAL_DECL : XML_DECL);
281 case '[': // <!DOCTYPE xxx [dtd]>
283 state = STATE_INTERNAL;
284 return getToken(XML_DECL);
290 private IToken nextCommentToken() {
291 state &= STATE_INTERNAL;
295 case ICharacterScanner.EOF:
300 case ICharacterScanner.EOF:
305 case ICharacterScanner.EOF:
316 return getToken(isInternal() ? DTD_INTERNAL_COMMENT : XML_COMMENT);
319 private IToken nextPIToken() {
320 state &= STATE_INTERNAL;
324 case ICharacterScanner.EOF:
329 case ICharacterScanner.EOF:
338 return getToken(isInternal() ? DTD_INTERNAL_PI : XML_PI);
341 private IToken nextCDATAToken() {
342 state = STATE_DEFAULT;
347 case ICharacterScanner.EOF:
352 case ICharacterScanner.EOF:
357 case ICharacterScanner.EOF:
369 return getToken(XML_CDATA);
372 private IToken nextConditionalToken() {
373 state = STATE_DEFAULT;
380 case ICharacterScanner.EOF:
385 case ICharacterScanner.EOF:
390 case ICharacterScanner.EOF:
407 case ICharacterScanner.EOF:
412 case ICharacterScanner.EOF:
428 return getToken(DTD_CONDITIONAL);
431 private IToken getToken(String type) {
432 length = position - offset;
439 return Token.UNDEFINED;
442 IToken token = (IToken) tokens.get(type);
444 token = new Token(type);
445 tokens.put(type, token);
451 private boolean isInternal() {
452 return (state & STATE_INTERNAL) != 0;
456 if (position >= end) {
457 return ICharacterScanner.EOF;
461 return document.getChar(position++);
462 } catch (BadLocationException e) {
464 return ICharacterScanner.EOF;
468 private void unread() {
473 * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
475 public int getTokenOffset() {
476 Assert.isTrue(offset>=0, Integer.toString(offset));
481 * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
483 public int getTokenLength() {
488 * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int, int)
490 public void setRange(IDocument document, int offset, int length) {
491 this.document = document;
492 this.end = offset + length;
494 this.offset = offset;
495 this.position = offset;
498 this.state = STATE_DEFAULT;
502 * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
504 // public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
505 // state = STATE_DEFAULT;
506 // if (partitionOffset > -1) {
507 // int delta = offset - partitionOffset;
509 // setRange(document, partitionOffset, length + delta);
513 // setRange(document, partitionOffset, length);
516 * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
518 public void setPartialRange(
519 IDocument document, int offset, int length,
520 String contentType, int partitionOffset
522 // boolean flag = false;
523 this.document = document;
524 this.end = offset + length;
526 // NB! Undocumented value: -1
527 if (partitionOffset >= 0) {
528 offset = partitionOffset;
532 this.offset = offset;
533 this.position = offset;
537 // state = STATE_DEFAULT;
540 if (contentType == XML_ATTRIBUTE) {
545 if (contentType == XML_TAG) {
546 state = isContinuationPartition() ? STATE_TAG : STATE_DEFAULT;
550 if (contentType == XML_DECL) {
551 state = isContinuationPartition() ? STATE_DECL : STATE_DEFAULT;
555 if (contentType == DTD_INTERNAL ||
556 contentType == DTD_INTERNAL_PI ||
557 contentType == DTD_INTERNAL_DECL ||
558 contentType == DTD_INTERNAL_COMMENT
560 state = STATE_INTERNAL;
564 state = STATE_DEFAULT;
567 private boolean isContinuationPartition() {
569 String type = document.getContentType(offset - 1);
571 if (type != IDocument.DEFAULT_CONTENT_TYPE) {
574 } catch (BadLocationException e) {}