1 package net.sourceforge.phpdt.internal.ui.text;
4 * (c) Copyright IBM Corp. 2000, 2001.
8 import org.eclipse.jface.text.IDocument;
9 import org.eclipse.jface.text.rules.ICharacterScanner;
10 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
11 import org.eclipse.jface.text.rules.IToken;
12 import org.eclipse.jface.text.rules.Token;
16 * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments,
17 * Java strings and Java characters.
19 public class FastJavaPartitionScanner implements IPartitionTokenScanner {
21 private final static String SKIP= "__skip"; //$NON-NLS-1$
22 public final static String JAVA_STRING= "__php_string"; //$NON-NLS-1$
23 public final static String JAVA_SINGLE_LINE_COMMENT= "__php_singleline_comment"; //$NON-NLS-1$
24 public final static String JAVA_MULTI_LINE_COMMENT= "__php_multiline_comment"; //$NON-NLS-1$
25 public final static String JAVA_DOC= "__php_phpdoc"; //$NON-NLS-1$
28 private static final int JAVA= 0;
29 private static final int SINGLE_LINE_COMMENT= 1;
30 private static final int MULTI_LINE_COMMENT= 2;
31 private static final int JAVADOC= 3;
32 private static final int CHARACTER= 4;
33 private static final int STRING= 5;
35 // beginning of prefixes and postfixes
36 private static final int NONE= 0;
37 private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER
38 private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
39 private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
40 private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
41 private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
42 private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
45 // private final BufferedRuleBasedScanner fScanner= new BufferedRuleBasedScanner(1000);
46 private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); // faster implementation
48 /** The offset of the last returned token. */
49 private int fTokenOffset;
50 /** The length of the last returned token. */
51 private int fTokenLength;
53 /** The state of the scanner. */
55 /** The last significant characters read. */
57 /** The amount of characters already read on first call to nextToken(). */
58 private int fPrefixLength;
60 // emulate JavaPartitionScanner
61 private static final boolean fgEmulate= false;
62 private int fJavaOffset;
63 private int fJavaLength;
65 private final IToken[] fTokens= new IToken[] {
67 new Token(JAVA_SINGLE_LINE_COMMENT),
68 new Token(JAVA_MULTI_LINE_COMMENT),
71 new Token(JAVA_STRING)
75 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
77 public IToken nextToken() {
79 // emulate JavaPartitionScanner
81 if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
82 fTokenOffset += fTokenLength;
90 fTokenOffset += fTokenLength;
91 fTokenLength= fPrefixLength;
94 final int ch= fScanner.read();
98 case ICharacterScanner.EOF:
99 if (fTokenLength > 0) {
100 fLast= NONE; // ignore last
101 return preFix(fState, JAVA, NONE, 0);
110 // emulate JavaPartitionScanner
111 if (!fgEmulate && fLast != CARRIAGE_RETURN) {
112 fLast= CARRIAGE_RETURN;
119 case SINGLE_LINE_COMMENT:
122 if (fTokenLength > 0) {
123 IToken token= fTokens[fState];
125 // emulate JavaPartitionScanner
131 fLast= CARRIAGE_RETURN;
151 case SINGLE_LINE_COMMENT:
154 // assert(fTokenLength > 0);
155 return postFix(fState);
163 if (!fgEmulate && fLast == CARRIAGE_RETURN) {
165 case SINGLE_LINE_COMMENT:
193 last= CARRIAGE_RETURN;
208 fLast= NONE; // ignore fLast
209 return preFix(fState, newState, last, 1);
222 if (fLast == SLASH) {
223 if (fTokenLength - getLastLength(fLast) > 0) {
224 return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
226 preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2);
227 fTokenOffset += fTokenLength;
228 fTokenLength= fPrefixLength;
239 if (fLast == SLASH) {
240 if (fTokenLength - getLastLength(fLast) > 0)
241 return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
243 preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2);
244 fTokenOffset += fTokenLength;
245 fTokenLength= fPrefixLength;
255 fLast= NONE; // ignore fLast
256 if (fTokenLength > 0)
257 return preFix(JAVA, CHARACTER, NONE, 1);
259 preFix(JAVA, CHARACTER, NONE, 1);
260 fTokenOffset += fTokenLength;
261 fTokenLength= fPrefixLength;
266 fLast= NONE; // ignore fLast
267 if (fTokenLength > 0)
268 return preFix(JAVA, STRING, NONE, 1);
270 preFix(JAVA, STRING, NONE, 1);
271 fTokenOffset += fTokenLength;
272 fTokenLength= fPrefixLength;
282 case SINGLE_LINE_COMMENT:
290 case SLASH_STAR_STAR:
291 return postFix(MULTI_LINE_COMMENT);
294 return postFix(JAVADOC);
313 case MULTI_LINE_COMMENT:
316 if (fLast == SLASH_STAR) {
317 fLast= SLASH_STAR_STAR;
328 return postFix(MULTI_LINE_COMMENT);
343 fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
348 if (fLast != BACKSLASH) {
349 return postFix(STRING);
365 fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
370 if (fLast != BACKSLASH) {
371 return postFix(CHARACTER);
387 private static final int getLastLength(int last) {
395 case CARRIAGE_RETURN:
404 case SLASH_STAR_STAR:
409 private final void consume() {
414 private final IToken postFix(int state) {
419 return fTokens[state];
422 private final IToken preFix(int state, int newState, int last, int prefixLength) {
423 // emulate JavaPartitionScanner
424 if (fgEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) {
425 fTokenLength -= getLastLength(fLast);
426 fJavaOffset= fTokenOffset;
427 fJavaLength= fTokenLength;
430 fPrefixLength= prefixLength;
432 return fTokens[state];
435 fTokenLength -= getLastLength(fLast);
437 fPrefixLength= prefixLength;
438 IToken token= fTokens[state];
444 private static int getState(String contentType) {
446 if (contentType == null)
449 else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT))
450 return SINGLE_LINE_COMMENT;
452 else if (contentType.equals(JAVA_MULTI_LINE_COMMENT))
453 return MULTI_LINE_COMMENT;
455 else if (contentType.equals(JAVA_DOC))
458 else if (contentType.equals(JAVA_STRING))
461 else if (contentType.equals(SKIP))
469 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
471 public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
473 fScanner.setRange(document, offset, length);
474 fTokenOffset= partitionOffset;
476 fPrefixLength= offset - partitionOffset;
479 if (offset == partitionOffset) {
480 // restart at beginning of partition
483 fState= getState(contentType);
486 // emulate JavaPartitionScanner
494 * @see ITokenScanner#setRange(IDocument, int, int)
496 public void setRange(IDocument document, int offset, int length) {
498 fScanner.setRange(document, offset, length);
499 fTokenOffset= offset;
505 // emulate JavaPartitionScanner
513 * @see ITokenScanner#getTokenLength()
515 public int getTokenLength() {
520 * @see ITokenScanner#getTokenOffset()
522 public int getTokenOffset() {