1
2
3
4
5
6
7
8
9
10
11 package org.syntax.jedit.tokenmarker;
12
13 import javax.swing.text.Segment;
14
15 import org.syntax.jedit.KeywordMap;
16 import org.syntax.jedit.SyntaxUtilities;
17
18 /***
19 * PHP token marker.
20 *
21 * @author Clancy Malcolm
22 * @version $Id: PHPTokenMarker.java,v 1.1 1999/12/14 04:20:35 sp Exp $
23 */
24 public class PHPTokenMarker extends TokenMarker
25 {
26 public static final byte SCRIPT = Token.INTERNAL_FIRST;
27
28 public byte markTokensImpl( byte token, Segment line, int lineIndex )
29 {
30 char[] array = line.array;
31 int offset = line.offset;
32 lastOffset = offset;
33 lastKeyword = offset;
34 int length = line.count + offset;
35 boolean backslash = false;
36
37 loop : for( int i = offset; i < length; i++ )
38 {
39 int i1 = ( i + 1 );
40
41 char c = array[i];
42 if( c == '//' )
43 {
44 backslash = !backslash;
45 continue;
46 }
47
48 switch( token )
49 {
50 case Token.NULL :
51 backslash = false;
52 switch( c )
53 {
54 case '<' :
55 addToken( i - lastOffset, token );
56 lastOffset = lastKeyword = i;
57 if( SyntaxUtilities.regionMatches( false, line, i1, "!--" ) )
58 {
59 i += 3;
60 token = Token.COMMENT1;
61 }
62 else if( SyntaxUtilities.regionMatches( true, line, i1, "?php" ) )
63 {
64 addToken( 5, Token.LABEL );
65 lastOffset = lastKeyword = ( i += 4 ) + 1;
66 token = SCRIPT;
67 }
68 else if( SyntaxUtilities.regionMatches( true, line, i1, "?" ) )
69 {
70 addToken( 2, Token.LABEL );
71 lastOffset = lastKeyword = ( i += 1 ) + 1;
72 token = SCRIPT;
73 }
74 else if( SyntaxUtilities.regionMatches( true, line, i1, "script>" ) )
75 {
76 addToken( 8, Token.LABEL );
77 lastOffset = lastKeyword = ( i += 7 ) + 1;
78 token = SCRIPT;
79 }
80 else
81 {
82 token = Token.KEYWORD1;
83 }
84 break;
85 case '&' :
86 addToken( i - lastOffset, token );
87 lastOffset = lastKeyword = i;
88 token = Token.KEYWORD2;
89 break;
90 }
91 break;
92 case Token.KEYWORD1 :
93 backslash = false;
94 if( c == '>' )
95 {
96 addToken( i1 - lastOffset, token );
97 lastOffset = lastKeyword = i1;
98 token = Token.NULL;
99 }
100 break;
101 case Token.KEYWORD2 :
102 backslash = false;
103 if( c == ';' )
104 {
105 addToken( i1 - lastOffset, token );
106 lastOffset = lastKeyword = i1;
107 token = Token.NULL;
108 break;
109 }
110 break;
111 case Token.COMMENT1 :
112 backslash = false;
113 if( SyntaxUtilities.regionMatches( false, line, i, "-->" ) )
114 {
115 addToken( i + 3 - lastOffset, token );
116 i += 2;
117 lastOffset = lastKeyword = i + 1;
118 token = Token.NULL;
119 }
120 break;
121 case SCRIPT :
122 switch( c )
123 {
124 case '<' :
125 backslash = false;
126 doKeyword( line, i, c );
127 if( SyntaxUtilities.regionMatches( true, line, i1, "/script>" ) )
128 {
129
130 addToken( i - lastOffset, Token.KEYWORD3 );
131 addToken( 9, Token.LABEL );
132 lastOffset = lastKeyword = ( i += 8 ) + 1;
133 token = Token.NULL;
134 }
135 else
136 {
137
138 addToken( i - lastOffset, Token.KEYWORD3 );
139 addToken( 1, Token.OPERATOR );
140 lastOffset = lastKeyword = i1;
141 }
142 break;
143 case '?' :
144 backslash = false;
145 doKeyword( line, i, c );
146 if( array[i1] == '>' )
147 {
148
149 addToken( i - lastOffset, Token.KEYWORD3 );
150 addToken( 2, Token.LABEL );
151 lastOffset = lastKeyword = ( i += 1 ) + 1;
152 token = Token.NULL;
153 }
154 else
155 {
156
157 addToken( i - lastOffset, Token.KEYWORD3 );
158 addToken( 1, Token.OPERATOR );
159 lastOffset = lastKeyword = i1;
160 }
161 break;
162 case '"' :
163 if( backslash )
164 backslash = false;
165 else
166 {
167 doKeyword( line, i, c );
168 addToken( i - lastOffset, Token.KEYWORD3 );
169 lastOffset = lastKeyword = i;
170 token = Token.LITERAL1;
171 }
172 break;
173 case '\'' :
174 if( backslash )
175 backslash = false;
176 else
177 {
178 doKeyword( line, i, c );
179 addToken( i - lastOffset, Token.KEYWORD3 );
180 lastOffset = lastKeyword = i;
181 token = Token.LITERAL2;
182 }
183 break;
184 case '#' :
185 doKeyword( line, i, c );
186 addToken( i - lastOffset, Token.KEYWORD3 );
187 addToken( length - i, Token.COMMENT2 );
188 lastOffset = lastKeyword = length;
189 break loop;
190 case '/' :
191 backslash = false;
192 doKeyword( line, i, c );
193 if( length - i > 1 )
194 {
195 addToken( i - lastOffset, Token.KEYWORD3 );
196 lastOffset = lastKeyword = i;
197 if( array[i1] == '/' )
198 {
199 addToken( length - i, Token.COMMENT2 );
200 lastOffset = lastKeyword = length;
201 break loop;
202 }
203 else if( array[i1] == '*' )
204 {
205 token = Token.COMMENT2;
206 }
207 else
208 {
209
210 addToken( i - lastOffset, Token.KEYWORD3 );
211 addToken( 1, Token.OPERATOR );
212 lastOffset = lastKeyword = i1;
213 }
214 }
215 else
216 {
217
218 addToken( i - lastOffset, Token.KEYWORD3 );
219 addToken( 1, Token.OPERATOR );
220 lastOffset = lastKeyword = i1;
221 }
222 break;
223 default :
224 backslash = false;
225 if( !Character.isLetterOrDigit( c ) && c != '_' && c != '$' )
226 {
227 doKeyword( line, i, c );
228 if( c != ' ' )
229 {
230
231 addToken( i - lastOffset, Token.KEYWORD3 );
232 addToken( 1, Token.OPERATOR );
233 lastOffset = lastKeyword = i1;
234 }
235 }
236 break;
237 }
238 break;
239 case Token.LITERAL1 :
240 if( backslash )
241 backslash = false;
242 else if( c == '"' )
243 {
244 addToken( i1 - lastOffset, Token.LITERAL1 );
245 lastOffset = lastKeyword = i1;
246 token = SCRIPT;
247 }
248 break;
249 case Token.LITERAL2 :
250 if( backslash )
251 backslash = false;
252 else if( c == '\'' )
253 {
254 addToken( i1 - lastOffset, Token.LITERAL1 );
255 lastOffset = lastKeyword = i1;
256 token = SCRIPT;
257 }
258 break;
259 case Token.COMMENT2 :
260 backslash = false;
261 if( c == '*' && length - i > 1 && array[i1] == '/' )
262 {
263 addToken( i + 2 - lastOffset, Token.COMMENT2 );
264 i += 1;
265 lastOffset = lastKeyword = i + 1;
266 token = SCRIPT;
267 }
268 break;
269 default :
270 throw new InternalError( "Invalid state: " + token );
271 }
272 }
273
274 switch( token )
275 {
276 case Token.LITERAL1 :
277 addToken( length - lastOffset, Token.LITERAL1 );
278 break;
279 case Token.LITERAL2 :
280 addToken( length - lastOffset, Token.LITERAL2 );
281 break;
282 case Token.KEYWORD2 :
283 addToken( length - lastOffset, Token.INVALID );
284 token = Token.NULL;
285 break;
286 case SCRIPT :
287 doKeyword( line, length, '\0' );
288 addToken( length - lastOffset, Token.KEYWORD3 );
289 break;
290 default :
291 addToken( length - lastOffset, token );
292 break;
293 }
294
295 return token;
296 }
297
298
299 private static KeywordMap keywords;
300 private int lastOffset;
301 private int lastKeyword;
302
303 static
304 {
305 keywords = new KeywordMap( false );
306 keywords.add( "function", Token.KEYWORD2 );
307 keywords.add( "class", Token.KEYWORD2 );
308 keywords.add( "var", Token.KEYWORD2 );
309 keywords.add( "require", Token.KEYWORD2 );
310 keywords.add( "include", Token.KEYWORD2 );
311 keywords.add( "else", Token.KEYWORD1 );
312 keywords.add( "elseif", Token.KEYWORD1 );
313 keywords.add( "do", Token.KEYWORD1 );
314 keywords.add( "for", Token.KEYWORD1 );
315 keywords.add( "if", Token.KEYWORD1 );
316 keywords.add( "endif", Token.KEYWORD1 );
317 keywords.add( "in", Token.KEYWORD1 );
318 keywords.add( "new", Token.KEYWORD1 );
319 keywords.add( "return", Token.KEYWORD1 );
320 keywords.add( "while", Token.KEYWORD1 );
321 keywords.add( "endwhile", Token.KEYWORD1 );
322 keywords.add( "with", Token.KEYWORD1 );
323 keywords.add( "break", Token.KEYWORD1 );
324 keywords.add( "switch", Token.KEYWORD1 );
325 keywords.add( "case", Token.KEYWORD1 );
326 keywords.add( "continue", Token.KEYWORD1 );
327 keywords.add( "default", Token.KEYWORD1 );
328 keywords.add( "echo", Token.KEYWORD1 );
329 keywords.add( "false", Token.KEYWORD1 );
330 keywords.add( "this", Token.KEYWORD1 );
331 keywords.add( "true", Token.KEYWORD1 );
332 keywords.add( "array", Token.KEYWORD1 );
333 keywords.add( "extends", Token.KEYWORD1 );
334 }
335
336 private boolean doKeyword( Segment line, int i, char c )
337 {
338 int i1 = i + 1;
339
340 int len = i - lastKeyword;
341 byte id = keywords.lookup( line, lastKeyword, len );
342 if( id != Token.NULL )
343 {
344 if( lastKeyword != lastOffset )
345 addToken( lastKeyword - lastOffset, Token.KEYWORD3 );
346 addToken( len, id );
347 lastOffset = i;
348 }
349 lastKeyword = i1;
350 return false;
351 }
352 }