View Javadoc

1   package org.syntax.jedit.tokenmarker;
2   
3   /*
4    * XMLTokenMarker.java - XML token marker
5    * Copyright (C) 1998, 1999 Slava Pestov
6    * Copyright (C) 2001 Tom Bradford
7    *
8    * You may use and modify this package for any purpose. Redistribution is
9    * permitted, in both source and binary form, provided that this notice
10   * remains intact in all source distributions of this package.
11   */
12  
13  import javax.swing.text.Segment;
14  
15  import org.syntax.jedit.SyntaxUtilities;
16  
17  /***
18   * XML Token Marker Rewrite
19   * 
20   * @author Tom Bradford
21   * @version $Id$
22   */
23  public class XMLTokenMarker extends TokenMarker
24  {
25  	public XMLTokenMarker()
26  	{
27  	}
28  
29  	public byte markTokensImpl( byte token, Segment line, int lineIndex )
30  	{
31  		char[] array = line.array;
32  		int offset = line.offset;
33  		int lastOffset = offset;
34  		int length = line.count + offset;
35  
36  		// Ugly hack to handle multi-line tags
37  		boolean sk1 = token == Token.KEYWORD1;
38  
39  		for( int i = offset; i < length; i++ )
40  		{
41  			int ip1 = i + 1;
42  			char c = array[i];
43  			switch( token )
44  			{
45  			case Token.NULL : // text
46  				switch( c )
47  				{
48  				case '<' :
49  					addToken( i - lastOffset, token );
50  					lastOffset = i;
51  					if( SyntaxUtilities.regionMatches( false, line, ip1, "!--" ) )
52  					{
53  						i += 3;
54  						token = Token.COMMENT1;
55  					}
56  					else if( array[ip1] == '!' )
57  					{
58  						i += 1;
59  						token = Token.COMMENT2;
60  					}
61  					else if( array[ip1] == '?' )
62  					{
63  						i += 1;
64  						token = Token.KEYWORD3;
65  					}
66  					else
67  						token = Token.KEYWORD1;
68  					break;
69  
70  				case '&' :
71  					addToken( i - lastOffset, token );
72  					lastOffset = i;
73  					token = Token.LABEL;
74  					break;
75  				}
76  				break;
77  
78  			case Token.KEYWORD1 : // tag
79  				switch( c )
80  				{
81  				case '>' :
82  					addToken( ip1 - lastOffset, token );
83  					lastOffset = ip1;
84  					token = Token.NULL;
85  					sk1 = false;
86  					break;
87  
88  				case ' ' :
89  				case '\t' :
90  					addToken( i - lastOffset, token );
91  					lastOffset = i;
92  					token = Token.KEYWORD2;
93  					sk1 = false;
94  					break;
95  
96  				default :
97  					if( sk1 )
98  					{
99  						token = Token.KEYWORD2;
100 						sk1 = false;
101 					}
102 					break;
103 				}
104 				break;
105 
106 			case Token.KEYWORD2 : // attribute
107 				switch( c )
108 				{
109 				case '>' :
110 					addToken( ip1 - lastOffset, token );
111 					lastOffset = ip1;
112 					token = Token.NULL;
113 					break;
114 
115 				case '/' :
116 					addToken( i - lastOffset, token );
117 					lastOffset = i;
118 					token = Token.KEYWORD1;
119 					break;
120 
121 				case '=' :
122 					addToken( i - lastOffset, token );
123 					lastOffset = i;
124 					token = Token.OPERATOR;
125 				}
126 				break;
127 
128 			case Token.OPERATOR : // equal for attribute
129 				switch( c )
130 				{
131 				case '\"' :
132 				case '\'' :
133 					addToken( i - lastOffset, token );
134 					lastOffset = i;
135 					if( c == '\"' )
136 						token = Token.LITERAL1;
137 					else
138 						token = Token.LITERAL2;
139 					break;
140 				}
141 				break;
142 
143 			case Token.LITERAL1 :
144 			case Token.LITERAL2 : // strings
145 				if( ( token == Token.LITERAL1 && c == '\"' ) || ( token == Token.LITERAL2 && c == '\'' ) )
146 				{
147 					addToken( ip1 - lastOffset, token );
148 					lastOffset = ip1;
149 					token = Token.KEYWORD1;
150 				}
151 				break;
152 
153 			case Token.LABEL : // entity
154 				if( c == ';' )
155 				{
156 					addToken( ip1 - lastOffset, token );
157 					lastOffset = ip1;
158 					token = Token.NULL;
159 					break;
160 				}
161 				break;
162 
163 			case Token.COMMENT1 : // Inside a comment
164 				if( SyntaxUtilities.regionMatches( false, line, i, "-->" ) )
165 				{
166 					addToken( ( i + 3 ) - lastOffset, token );
167 					lastOffset = i + 3;
168 					token = Token.NULL;
169 				}
170 				break;
171 
172 			case Token.COMMENT2 : // Inside a declaration
173 				if( SyntaxUtilities.regionMatches( false, line, i, ">" ) )
174 				{
175 					addToken( ip1 - lastOffset, token );
176 					lastOffset = ip1;
177 					token = Token.NULL;
178 				}
179 				break;
180 
181 			case Token.KEYWORD3 : // Inside a processor instruction
182 				if( SyntaxUtilities.regionMatches( false, line, i, "?>" ) )
183 				{
184 					addToken( ( i + 2 ) - lastOffset, token );
185 					lastOffset = i + 2;
186 					token = Token.NULL;
187 				}
188 				break;
189 
190 			default :
191 				throw new InternalError( "Invalid state: " + token );
192 			}
193 		}
194 
195 		switch( token )
196 		{
197 		case Token.LABEL :
198 			addToken( length - lastOffset, Token.INVALID );
199 			token = Token.NULL;
200 			break;
201 
202 		default :
203 			addToken( length - lastOffset, token );
204 			break;
205 		}
206 
207 		return token;
208 	}
209 }