1
2
3
4
5
6
7
8
9
10 package org.syntax.jedit.tokenmarker;
11
12 import javax.swing.text.Segment;
13
14 import org.syntax.jedit.KeywordMap;
15 import org.syntax.jedit.SyntaxUtilities;
16
17 /***
18 * HTML token marker.
19 *
20 * @author Slava Pestov
21 * @version $Id: HTMLTokenMarker.java,v 1.34 1999/12/13 03:40:29 sp Exp $
22 */
23 public class HTMLTokenMarker extends TokenMarker
24 {
25 public static final byte JAVASCRIPT = Token.INTERNAL_FIRST;
26
27 public HTMLTokenMarker()
28 {
29 this( true );
30 }
31
32 public HTMLTokenMarker( boolean js )
33 {
34 this.js = js;
35 keywords = JavaScriptTokenMarker.getKeywords();
36 }
37
38 public byte markTokensImpl( byte token, Segment line, int lineIndex )
39 {
40 char[] array = line.array;
41 int offset = line.offset;
42 lastOffset = offset;
43 lastKeyword = offset;
44 int length = line.count + offset;
45 boolean backslash = false;
46
47 loop : for( int i = offset; i < length; i++ )
48 {
49 int i1 = ( i + 1 );
50
51 char c = array[i];
52 if( c == '//' )
53 {
54 backslash = !backslash;
55 continue;
56 }
57
58 switch( token )
59 {
60 case Token.NULL :
61 backslash = false;
62 switch( c )
63 {
64 case '<' :
65 addToken( i - lastOffset, token );
66 lastOffset = lastKeyword = i;
67 if( SyntaxUtilities.regionMatches( false, line, i1, "!--" ) )
68 {
69 i += 3;
70 token = Token.COMMENT1;
71 }
72 else if( js && SyntaxUtilities.regionMatches( true, line, i1, "script>" ) )
73 {
74 addToken( 8, Token.KEYWORD1 );
75 lastOffset = lastKeyword = ( i += 8 );
76 token = JAVASCRIPT;
77 }
78 else
79 {
80 token = Token.KEYWORD1;
81 }
82 break;
83 case '&' :
84 addToken( i - lastOffset, token );
85 lastOffset = lastKeyword = i;
86 token = Token.KEYWORD2;
87 break;
88 }
89 break;
90 case Token.KEYWORD1 :
91 backslash = false;
92 if( c == '>' )
93 {
94 addToken( i1 - lastOffset, token );
95 lastOffset = lastKeyword = i1;
96 token = Token.NULL;
97 }
98 break;
99 case Token.KEYWORD2 :
100 backslash = false;
101 if( c == ';' )
102 {
103 addToken( i1 - lastOffset, token );
104 lastOffset = lastKeyword = i1;
105 token = Token.NULL;
106 break;
107 }
108 break;
109 case Token.COMMENT1 :
110 backslash = false;
111 if( SyntaxUtilities.regionMatches( false, line, i, "-->" ) )
112 {
113 addToken( ( i + 3 ) - lastOffset, token );
114 lastOffset = lastKeyword = i + 3;
115 token = Token.NULL;
116 }
117 break;
118 case JAVASCRIPT :
119 switch( c )
120 {
121 case '<' :
122 backslash = false;
123 doKeyword( line, i, c );
124 if( SyntaxUtilities.regionMatches( true, line, i1, "/script>" ) )
125 {
126 addToken( i - lastOffset, Token.NULL );
127 addToken( 9, Token.KEYWORD1 );
128 lastOffset = lastKeyword = ( i += 9 );
129 token = Token.NULL;
130 }
131 break;
132 case '"' :
133 if( backslash )
134 backslash = false;
135 else
136 {
137 doKeyword( line, i, c );
138 addToken( i - lastOffset, Token.NULL );
139 lastOffset = lastKeyword = i;
140 token = Token.LITERAL1;
141 }
142 break;
143 case '\'' :
144 if( backslash )
145 backslash = false;
146 else
147 {
148 doKeyword( line, i, c );
149 addToken( i - lastOffset, Token.NULL );
150 lastOffset = lastKeyword = i;
151 token = Token.LITERAL2;
152 }
153 break;
154 case '/' :
155 backslash = false;
156 doKeyword( line, i, c );
157 if( length - i > 1 )
158 {
159 addToken( i - lastOffset, Token.NULL );
160 lastOffset = lastKeyword = i;
161 if( array[i1] == '/' )
162 {
163 addToken( length - i, Token.COMMENT2 );
164 lastOffset = lastKeyword = length;
165 break loop;
166 }
167 else if( array[i1] == '*' )
168 {
169 token = Token.COMMENT2;
170 }
171 }
172 break;
173 default :
174 backslash = false;
175 if( !Character.isLetterOrDigit( c ) && c != '_' )
176 doKeyword( line, i, c );
177 break;
178 }
179 break;
180 case Token.LITERAL1 :
181 if( backslash )
182 backslash = false;
183 else if( c == '"' )
184 {
185 addToken( i1 - lastOffset, Token.LITERAL1 );
186 lastOffset = lastKeyword = i1;
187 token = JAVASCRIPT;
188 }
189 break;
190 case Token.LITERAL2 :
191 if( backslash )
192 backslash = false;
193 else if( c == '\'' )
194 {
195 addToken( i1 - lastOffset, Token.LITERAL1 );
196 lastOffset = lastKeyword = i1;
197 token = JAVASCRIPT;
198 }
199 break;
200 case Token.COMMENT2 :
201 backslash = false;
202 if( c == '*' && length - i > 1 && array[i1] == '/' )
203 {
204 addToken( ( i += 2 ) - lastOffset, Token.COMMENT2 );
205 lastOffset = lastKeyword = i;
206 token = JAVASCRIPT;
207 }
208 break;
209 default :
210 throw new InternalError( "Invalid state: " + token );
211 }
212 }
213
214 switch( token )
215 {
216 case Token.LITERAL1 :
217 case Token.LITERAL2 :
218 addToken( length - lastOffset, Token.INVALID );
219 token = JAVASCRIPT;
220 break;
221 case Token.KEYWORD2 :
222 addToken( length - lastOffset, Token.INVALID );
223 token = Token.NULL;
224 break;
225 case JAVASCRIPT :
226 doKeyword( line, length, '\0' );
227 addToken( length - lastOffset, Token.NULL );
228 break;
229 default :
230 addToken( length - lastOffset, token );
231 break;
232 }
233
234 return token;
235 }
236
237
238 private KeywordMap keywords;
239 private boolean js;
240 private int lastOffset;
241 private int lastKeyword;
242
243 private boolean doKeyword( Segment line, int i, char c )
244 {
245 int i1 = i + 1;
246
247 int len = i - lastKeyword;
248 byte id = keywords.lookup( line, lastKeyword, len );
249 if( id != Token.NULL )
250 {
251 if( lastKeyword != lastOffset )
252 addToken( lastKeyword - lastOffset, Token.NULL );
253 addToken( len, id );
254 lastOffset = i;
255 }
256 lastKeyword = i1;
257 return false;
258 }
259 }