001: package org.syntax.jedit.tokenmarker;
002:
003: /*
004: * XMLTokenMarker.java - XML token marker
005: * Copyright (C) 1998, 1999 Slava Pestov
006: * Copyright (C) 2001 Tom Bradford
007: *
008: * You may use and modify this package for any purpose. Redistribution is
009: * permitted, in both source and binary form, provided that this notice
010: * remains intact in all source distributions of this package.
011: */
012:
013: import javax.swing.text.Segment;
014:
015: import org.syntax.jedit.SyntaxUtilities;
016:
017: /**
018: * XML Token Marker Rewrite
019: *
020: * @author Tom Bradford
021: * @version $Id$
022: */
023: public class XMLTokenMarker extends TokenMarker {
024: public XMLTokenMarker() {
025: }
026:
027: public byte markTokensImpl(byte token, Segment line, int lineIndex) {
028: char[] array = line.array;
029: int offset = line.offset;
030: int lastOffset = offset;
031: int length = line.count + offset;
032:
033: // Ugly hack to handle multi-line tags
034: boolean sk1 = token == Token.KEYWORD1;
035:
036: for (int i = offset; i < length; i++) {
037: int ip1 = i + 1;
038: char c = array[i];
039: switch (token) {
040: case Token.NULL: // text
041: switch (c) {
042: case '<':
043: addToken(i - lastOffset, token);
044: lastOffset = i;
045: if (SyntaxUtilities.regionMatches(false, line, ip1,
046: "!--")) {
047: i += 3;
048: token = Token.COMMENT1;
049: } else if (array[ip1] == '!') {
050: i += 1;
051: token = Token.COMMENT2;
052: } else if (array[ip1] == '?') {
053: i += 1;
054: token = Token.KEYWORD3;
055: } else
056: token = Token.KEYWORD1;
057: break;
058:
059: case '&':
060: addToken(i - lastOffset, token);
061: lastOffset = i;
062: token = Token.LABEL;
063: break;
064: }
065: break;
066:
067: case Token.KEYWORD1: // tag
068: switch (c) {
069: case '>':
070: addToken(ip1 - lastOffset, token);
071: lastOffset = ip1;
072: token = Token.NULL;
073: sk1 = false;
074: break;
075:
076: case ' ':
077: case '\t':
078: addToken(i - lastOffset, token);
079: lastOffset = i;
080: token = Token.KEYWORD2;
081: sk1 = false;
082: break;
083:
084: default:
085: if (sk1) {
086: token = Token.KEYWORD2;
087: sk1 = false;
088: }
089: break;
090: }
091: break;
092:
093: case Token.KEYWORD2: // attribute
094: switch (c) {
095: case '>':
096: addToken(ip1 - lastOffset, token);
097: lastOffset = ip1;
098: token = Token.NULL;
099: break;
100:
101: case '/':
102: addToken(i - lastOffset, token);
103: lastOffset = i;
104: token = Token.KEYWORD1;
105: break;
106:
107: case '=':
108: addToken(i - lastOffset, token);
109: lastOffset = i;
110: token = Token.OPERATOR;
111: }
112: break;
113:
114: case Token.OPERATOR: // equal for attribute
115: switch (c) {
116: case '\"':
117: case '\'':
118: addToken(i - lastOffset, token);
119: lastOffset = i;
120: if (c == '\"')
121: token = Token.LITERAL1;
122: else
123: token = Token.LITERAL2;
124: break;
125: }
126: break;
127:
128: case Token.LITERAL1:
129: case Token.LITERAL2: // strings
130: if ((token == Token.LITERAL1 && c == '\"')
131: || (token == Token.LITERAL2 && c == '\'')) {
132: addToken(ip1 - lastOffset, token);
133: lastOffset = ip1;
134: token = Token.KEYWORD1;
135: }
136: break;
137:
138: case Token.LABEL: // entity
139: if (c == ';') {
140: addToken(ip1 - lastOffset, token);
141: lastOffset = ip1;
142: token = Token.NULL;
143: break;
144: }
145: break;
146:
147: case Token.COMMENT1: // Inside a comment
148: if (SyntaxUtilities
149: .regionMatches(false, line, i, "-->")) {
150: addToken((i + 3) - lastOffset, token);
151: lastOffset = i + 3;
152: token = Token.NULL;
153: }
154: break;
155:
156: case Token.COMMENT2: // Inside a declaration
157: if (SyntaxUtilities.regionMatches(false, line, i, ">")) {
158: addToken(ip1 - lastOffset, token);
159: lastOffset = ip1;
160: token = Token.NULL;
161: }
162: break;
163:
164: case Token.KEYWORD3: // Inside a processor instruction
165: if (SyntaxUtilities.regionMatches(false, line, i, "?>")) {
166: addToken((i + 2) - lastOffset, token);
167: lastOffset = i + 2;
168: token = Token.NULL;
169: }
170: break;
171:
172: default:
173: throw new InternalError("Invalid state: " + token);
174: }
175: }
176:
177: switch (token) {
178: case Token.LABEL:
179: addToken(length - lastOffset, Token.INVALID);
180: token = Token.NULL;
181: break;
182:
183: default:
184: addToken(length - lastOffset, token);
185: break;
186: }
187:
188: return token;
189: }
190: }
|