KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > FastJavaPartitionScanner


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.text;
12
13
14 import org.eclipse.jface.text.IDocument;
15 import org.eclipse.jface.text.rules.ICharacterScanner;
16 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
17 import org.eclipse.jface.text.rules.IToken;
18 import org.eclipse.jface.text.rules.Token;
19
20 import org.eclipse.jdt.ui.text.IJavaPartitions;
21
22
23 /**
24  * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments,
25  * Java strings and Java characters.
26  */

27 public class FastJavaPartitionScanner implements IPartitionTokenScanner, IJavaPartitions {
28
29     // states
30
private static final int JAVA= 0;
31     private static final int SINGLE_LINE_COMMENT= 1;
32     private static final int MULTI_LINE_COMMENT= 2;
33     private static final int JAVADOC= 3;
34     private static final int CHARACTER= 4;
35     private static final int STRING= 5;
36
37     // beginning of prefixes and postfixes
38
private static final int NONE= 0;
39     private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER
40
private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
41
private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
42
private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
43
private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
44
private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
45

46     /** The scanner. */
47     private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); // faster implementation
48

49     /** The offset of the last returned token. */
50     private int fTokenOffset;
51     /** The length of the last returned token. */
52     private int fTokenLength;
53
54     /** The state of the scanner. */
55     private int fState;
56     /** The last significant characters read. */
57     private int fLast;
58     /** The amount of characters already read on first call to nextToken(). */
59     private int fPrefixLength;
60
61     // emulate JavaPartitionScanner
62
private boolean fEmulate= false;
63     private int fJavaOffset;
64     private int fJavaLength;
65
66     private final IToken[] fTokens= new IToken[] {
67         new Token(null),
68         new Token(JAVA_SINGLE_LINE_COMMENT),
69         new Token(JAVA_MULTI_LINE_COMMENT),
70         new Token(JAVA_DOC),
71         new Token(JAVA_CHARACTER),
72         new Token(JAVA_STRING)
73     };
74
75     public FastJavaPartitionScanner(boolean emulate) {
76         fEmulate= emulate;
77     }
78
79     public FastJavaPartitionScanner() {
80         this(false);
81     }
82
83     /*
84      * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
85      */

86     public IToken nextToken() {
87
88         // emulate JavaPartitionScanner
89
if (fEmulate) {
90             if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
91                 fTokenOffset += fTokenLength;
92                 return fTokens[JAVA];
93             } else {
94                 fJavaOffset= -1;
95                 fJavaLength= 0;
96             }
97         }
98
99         fTokenOffset += fTokenLength;
100         fTokenLength= fPrefixLength;
101
102         while (true) {
103             final int ch= fScanner.read();
104
105             // characters
106
switch (ch) {
107             case ICharacterScanner.EOF:
108                 if (fTokenLength > 0) {
109                     fLast= NONE; // ignore last
110
return preFix(fState, JAVA, NONE, 0);
111
112                 } else {
113                     fLast= NONE;
114                     fPrefixLength= 0;
115                     return Token.EOF;
116                 }
117
118             case '\r':
119                 // emulate JavaPartitionScanner
120
if (!fEmulate && fLast != CARRIAGE_RETURN) {
121                         fLast= CARRIAGE_RETURN;
122                         fTokenLength++;
123                         continue;
124
125                 } else {
126
127                     switch (fState) {
128                     case SINGLE_LINE_COMMENT:
129                     case CHARACTER:
130                     case STRING:
131                         if (fTokenLength > 0) {
132                             IToken token= fTokens[fState];
133
134                             // emulate JavaPartitionScanner
135
if (fEmulate) {
136                                 fTokenLength++;
137                                 fLast= NONE;
138                                 fPrefixLength= 0;
139                             } else {
140                                 fLast= CARRIAGE_RETURN;
141                                 fPrefixLength= 1;
142                             }
143
144                             fState= JAVA;
145                             return token;
146
147                         } else {
148                             consume();
149                             continue;
150                         }
151
152                     default:
153                         consume();
154                         continue;
155                     }
156                 }
157
158             case '\n':
159                 switch (fState) {
160                 case SINGLE_LINE_COMMENT:
161                 case CHARACTER:
162                 case STRING:
163                     // assert(fTokenLength > 0);
164
return postFix(fState);
165
166                 default:
167                     consume();
168                     continue;
169                 }
170
171             default:
172                 if (!fEmulate && fLast == CARRIAGE_RETURN) {
173                     switch (fState) {
174                     case SINGLE_LINE_COMMENT:
175                     case CHARACTER:
176                     case STRING:
177
178                         int last;
179                         int newState;
180                         switch (ch) {
181                         case '/':
182                             last= SLASH;
183                             newState= JAVA;
184                             break;
185
186                         case '*':
187                             last= STAR;
188                             newState= JAVA;
189                             break;
190
191                         case '\'':
192                             last= NONE;
193                             newState= CHARACTER;
194                             break;
195
196                         case '"':
197                             last= NONE;
198                             newState= STRING;
199                             break;
200
201                         case '\r':
202                             last= CARRIAGE_RETURN;
203                             newState= JAVA;
204                             break;
205
206                         case '\\':
207                             last= BACKSLASH;
208                             newState= JAVA;
209                             break;
210
211                         default:
212                             last= NONE;
213                             newState= JAVA;
214                             break;
215                         }
216
217                         fLast= NONE; // ignore fLast
218
return preFix(fState, newState, last, 1);
219
220                     default:
221                         break;
222                     }
223                 }
224             }
225
226             // states
227
switch (fState) {
228             case JAVA:
229                 switch (ch) {
230                 case '/':
231                     if (fLast == SLASH) {
232                         if (fTokenLength - getLastLength(fLast) > 0) {
233                             return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
234                         } else {
235                             preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
236                             fTokenOffset += fTokenLength;
237                             fTokenLength= fPrefixLength;
238                             break;
239                         }
240
241                     } else {
242                         fTokenLength++;
243                         fLast= SLASH;
244                         break;
245                     }
246
247                 case '*':
248                     if (fLast == SLASH) {
249                         if (fTokenLength - getLastLength(fLast) > 0)
250                             return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
251                         else {
252                             preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
253                             fTokenOffset += fTokenLength;
254                             fTokenLength= fPrefixLength;
255                             break;
256                         }
257
258                     } else {
259                         consume();
260                         break;
261                     }
262
263                 case '\'':
264                     fLast= NONE; // ignore fLast
265
if (fTokenLength > 0)
266                         return preFix(JAVA, CHARACTER, NONE, 1);
267                     else {
268                         preFix(JAVA, CHARACTER, NONE, 1);
269                         fTokenOffset += fTokenLength;
270                         fTokenLength= fPrefixLength;
271                         break;
272                     }
273
274                 case '"':
275                     fLast= NONE; // ignore fLast
276
if (fTokenLength > 0)
277                         return preFix(JAVA, STRING, NONE, 1);
278                     else {
279                         preFix(JAVA, STRING, NONE, 1);
280                         fTokenOffset += fTokenLength;
281                         fTokenLength= fPrefixLength;
282                         break;
283                     }
284
285                 default:
286                     consume();
287                     break;
288                 }
289                 break;
290
291             case SINGLE_LINE_COMMENT:
292                 consume();
293                 break;
294
295             case JAVADOC:
296                 switch (ch) {
297                 case '/':
298                     switch (fLast) {
299                     case SLASH_STAR_STAR:
300                         return postFix(MULTI_LINE_COMMENT);
301
302                     case STAR:
303                         return postFix(JAVADOC);
304
305                     default:
306                         consume();
307                         break;
308                     }
309                     break;
310
311                 case '*':
312                     fTokenLength++;
313                     fLast= STAR;
314                     break;
315
316                 default:
317                     consume();
318                     break;
319                 }
320                 break;
321
322             case MULTI_LINE_COMMENT:
323                 switch (ch) {
324                 case '*':
325                     if (fLast == SLASH_STAR) {
326                         fLast= SLASH_STAR_STAR;
327                         fTokenLength++;
328                         fState= JAVADOC;
329                     } else {
330                         fTokenLength++;
331                         fLast= STAR;
332                     }
333                     break;
334
335                 case '/':
336                     if (fLast == STAR) {
337                         return postFix(MULTI_LINE_COMMENT);
338                     } else {
339                         consume();
340                         break;
341                     }
342
343                 default:
344                     consume();
345                     break;
346                 }
347                 break;
348
349             case STRING:
350                 switch (ch) {
351                 case '\\':
352                     fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
353                     fTokenLength++;
354                     break;
355
356                 case '\"':
357                     if (fLast != BACKSLASH) {
358                         return postFix(STRING);
359
360                     } else {
361                         consume();
362                         break;
363                     }
364
365                 default:
366                     consume();
367                     break;
368                 }
369                 break;
370
371             case CHARACTER:
372                 switch (ch) {
373                 case '\\':
374                     fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
375                     fTokenLength++;
376                     break;
377
378                 case '\'':
379                     if (fLast != BACKSLASH) {
380                         return postFix(CHARACTER);
381
382                     } else {
383                         consume();
384                         break;
385                     }
386
387                 default:
388                     consume();
389                     break;
390                 }
391                 break;
392             }
393         }
394     }
395
396     private static final int getLastLength(int last) {
397         switch (last) {
398         default:
399             return -1;
400
401         case NONE:
402             return 0;
403
404         case CARRIAGE_RETURN:
405         case BACKSLASH:
406         case SLASH:
407         case STAR:
408             return 1;
409
410         case SLASH_STAR:
411             return 2;
412
413         case SLASH_STAR_STAR:
414             return 3;
415         }
416     }
417
418     private final void consume() {
419         fTokenLength++;
420         fLast= NONE;
421     }
422
423     private final IToken postFix(int state) {
424         fTokenLength++;
425         fLast= NONE;
426         fState= JAVA;
427         fPrefixLength= 0;
428         return fTokens[state];
429     }
430
431     private final IToken preFix(int state, int newState, int last, int prefixLength) {
432         // emulate JavaPartitionScanner
433
if (fEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) {
434             fTokenLength -= getLastLength(fLast);
435             fJavaOffset= fTokenOffset;
436             fJavaLength= fTokenLength;
437             fTokenLength= 1;
438             fState= newState;
439             fPrefixLength= prefixLength;
440             fLast= last;
441             return fTokens[state];
442
443         } else {
444             fTokenLength -= getLastLength(fLast);
445             fLast= last;
446             fPrefixLength= prefixLength;
447             IToken token= fTokens[state];
448             fState= newState;
449             return token;
450         }
451     }
452
453     private static int getState(String JavaDoc contentType) {
454
455         if (contentType == null)
456             return JAVA;
457
458         else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT))
459             return SINGLE_LINE_COMMENT;
460
461         else if (contentType.equals(JAVA_MULTI_LINE_COMMENT))
462             return MULTI_LINE_COMMENT;
463
464         else if (contentType.equals(JAVA_DOC))
465             return JAVADOC;
466
467         else if (contentType.equals(JAVA_STRING))
468             return STRING;
469
470         else if (contentType.equals(JAVA_CHARACTER))
471             return CHARACTER;
472
473         else
474             return JAVA;
475     }
476
477     /*
478      * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
479      */

480     public void setPartialRange(IDocument document, int offset, int length, String JavaDoc contentType, int partitionOffset) {
481
482         fScanner.setRange(document, offset, length);
483         fTokenOffset= partitionOffset;
484         fTokenLength= 0;
485         fPrefixLength= offset - partitionOffset;
486         fLast= NONE;
487
488         if (offset == partitionOffset) {
489             // restart at beginning of partition
490
fState= JAVA;
491         } else {
492             fState= getState(contentType);
493         }
494
495         // emulate JavaPartitionScanner
496
if (fEmulate) {
497             fJavaOffset= -1;
498             fJavaLength= 0;
499         }
500     }
501
502     /*
503      * @see ITokenScanner#setRange(IDocument, int, int)
504      */

505     public void setRange(IDocument document, int offset, int length) {
506
507         fScanner.setRange(document, offset, length);
508         fTokenOffset= offset;
509         fTokenLength= 0;
510         fPrefixLength= 0;
511         fLast= NONE;
512         fState= JAVA;
513
514         // emulate JavaPartitionScanner
515
if (fEmulate) {
516             fJavaOffset= -1;
517             fJavaLength= 0;
518         }
519     }
520
521     /*
522      * @see ITokenScanner#getTokenLength()
523      */

524     public int getTokenLength() {
525         return fTokenLength;
526     }
527
528     /*
529      * @see ITokenScanner#getTokenOffset()
530      */

531     public int getTokenOffset() {
532         return fTokenOffset;
533     }
534
535 }
536
Popular Tags