KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > ext > ExtSyntaxSupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor.ext;
21
22 import java.util.Map JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import javax.swing.event.DocumentListener JavaDoc;
25 import javax.swing.event.DocumentEvent JavaDoc;
26 import javax.swing.text.BadLocationException JavaDoc;
27 import javax.swing.text.JTextComponent JavaDoc;
28 import org.netbeans.editor.BaseDocument;
29 import org.netbeans.editor.SyntaxSupport;
30 import org.netbeans.editor.Utilities;
31 import org.netbeans.editor.TokenProcessor;
32 import org.netbeans.editor.TokenID;
33 import org.netbeans.editor.TokenContextPath;
34 import org.netbeans.editor.TokenItem;
35 import org.netbeans.editor.SettingsNames;
36 import org.netbeans.editor.FinderFactory;
37 import org.netbeans.editor.TextBatchProcessor;
38 import org.netbeans.editor.Analyzer;
39
40 /**
41 * Support methods for syntax analyzes
42 *
43 * @author Miloslav Metelka
44 * @version 1.00
45 */

46
47 public class ExtSyntaxSupport extends SyntaxSupport {
48
49     // used in ExtKit
50

51     /** Schedule content update making completion visible. */
52     public static final int COMPLETION_POPUP = 0;
53     /** Cancel request without changing completion visibility. */
54     public static final int COMPLETION_CANCEL = 1;
55     /** Update content immediatelly if it's currently visible. */
56     public static final int COMPLETION_REFRESH = 2;
57     /** Schedule content update if it's currently visible. */
58     public static final int COMPLETION_POST_REFRESH = 3;
59     /** Hide completion. */
60     public static final int COMPLETION_HIDE = 4;
61
62     private static final TokenID[] EMPTY_TOKEN_ID_ARRAY = new TokenID[0];
63
64     /** Listens for the changes on the document. Children can override
65     * the documentModified() method to perform some processing.
66     */

67     private DocumentListener JavaDoc docL;
68
69     /** Map holding the [position, local-variable-map] pairs */
70     private HashMap JavaDoc localVarMaps = new HashMap JavaDoc();
71
72     /** Map holding the [position, global-variable-map] pairs */
73     private HashMap JavaDoc globalVarMaps = new HashMap JavaDoc();
74
75     public ExtSyntaxSupport(BaseDocument doc) {
76         super(doc);
77
78         // Create listener to listen on document changes
79
docL = new DocumentListener JavaDoc() {
80                    public void insertUpdate(DocumentEvent JavaDoc evt) {
81                        documentModified(evt);
82                    }
83
84                    public void removeUpdate(DocumentEvent JavaDoc evt) {
85                        documentModified(evt);
86                    }
87
88                    public void changedUpdate(DocumentEvent JavaDoc evt) {
89                    }
90                };
91         getDocument().addDocumentListener(docL);
92     }
93
94     /** Get the chain of the tokens for the given block of text.
95     * The returned chain of token-items reflects the tokens
96     * as they occur in the text and therefore the first token
97     * can start at the slightly lower position than the requested one.
98     * The chain itself can be extended automatically when
99     * reaching the first chain item and calling <tt>getPrevious()</tt>
100     * on it. Another chunk of the tokens will be parsed and
101     * the head of the chain will be extended. However this happens
102     * only in case there was no modification performed to the document
103     * between the creation of the chain and this moment. Otherwise
104     * this call throws <tt>IllegalStateException</tt>.
105     *
106     * @param startOffset starting position of the block
107     * @param endOffset ending position of the block
108     * @return the first item of the token-item chain or null if there are
109     * no tokens in the given area or the area is so small that it lays
110     * inside one token. To prevent this provide the area that spans a new-line.
111     */

112     public TokenItem getTokenChain(int startOffset, int endOffset)
113     throws BadLocationException JavaDoc {
114
115         if (startOffset < 0) {
116         throw new IllegalArgumentException JavaDoc("startOffset=" + startOffset + " < 0"); // NOI18N
117
}
118     if (startOffset > endOffset) {
119         throw new IllegalArgumentException JavaDoc("startOffset=" + startOffset // NOI18N
120
+ " > endOffset=" + endOffset); // NOI18N
121
}
122         TokenItem chain = null;
123         BaseDocument doc = getDocument();
124         doc.readLock();
125         try {
126             int docLen = doc.getLength();
127             endOffset = Math.min(endOffset, docLen);
128             if( startOffset < docLen ) {
129                 TokenItemTP tp = new TokenItemTP();
130                 tp.targetOffset = endOffset;
131                 tokenizeText(tp, startOffset, endOffset, false);
132                 chain = tp.getTokenChain();
133             }
134         } finally {
135             doc.readUnlock();
136         }
137
138         return chain;
139     }
140
141     /** Called when the document was modified by either the insert or removal.
142     * @param evt event received with the modification notification. getType()
143     * can be used to obtain the type of the event.
144     */

145     protected void documentModified(DocumentEvent JavaDoc evt) {
146         // Invalidate variable maps
147
localVarMaps.clear();
148         globalVarMaps.clear();
149     }
150
151     /** Get the bracket finder that will search for the matching bracket
152      * or null if the bracket character doesn't belong to bracket
153      * characters.
154      */

155     protected BracketFinder getMatchingBracketFinder(char bracketChar) {
156         BracketFinder bf = new BracketFinder(bracketChar);
157         if (bf.moveCount == 0) { // not valid bracket char
158
bf = null;
159         }
160
161         return bf;
162     }
163
164     /** Find matching bracket or more generally block
165      * that matches with the current position.
166      * @param offset position of the starting bracket
167      * @param simple whether the search should skip comment and possibly other areas.
168      * This can be useful when the speed is critical, because the simple
169      * search is faster.
170      * @return array of integers containing starting and ending position
171      * of the block in the document. Null is returned if there's
172      * no matching block.
173      */

174     public int[] findMatchingBlock(int offset, boolean simpleSearch)
175     throws BadLocationException JavaDoc {
176         char bracketChar = getDocument().getChars(offset, 1)[0];
177         int foundPos = -1;
178
179         final BracketFinder bf = getMatchingBracketFinder(bracketChar);
180
181         if (bf != null) { // valid finder
182
if (!simpleSearch) {
183                 TokenID tokenID = getTokenID(offset);
184                 TokenID[] bst = getBracketSkipTokens();
185                 for (int i = bst.length - 1; i >= 0; i--) {
186                     if (tokenID == bst[i]) {
187                         simpleSearch = true; // turn to simple search
188
break;
189                     }
190                 }
191             }
192
193             if (simpleSearch) { // don't exclude comments etc.
194
if (bf.isForward()) {
195                     foundPos = getDocument().find(bf, offset, -1);
196                 } else {
197                     foundPos = getDocument().find(bf, offset + 1, 0);
198                 }
199
200             } else { // exclude comments etc. from the search
201
TextBatchProcessor tbp = new TextBatchProcessor() {
202                      public int processTextBatch(BaseDocument doc, int startPos, int endPos,
203                                                  boolean lastBatch) {
204                          try {
205                              int[] blks = getTokenBlocks(startPos, endPos, getBracketSkipTokens());
206                              return findOutsideBlocks(bf, startPos, endPos, blks);
207                          } catch (BadLocationException JavaDoc e) {
208                              return -1;
209                          }
210                      }
211                 };
212
213                 if (bf.isForward()) {
214                     foundPos = getDocument().processText(tbp, offset, -1);
215                 } else {
216                     foundPos = getDocument().processText(tbp, offset + 1, 0);
217                 }
218             }
219         }
220
221         return (foundPos != -1) ? new int[] { foundPos, foundPos + 1 } : null;
222     }
223
224     /** Get the array of token IDs that should be skipped when
225     * searching for matching bracket. It usually includes comments
226     * and character and string constants. Returns empty array by default.
227     */

228     protected TokenID[] getBracketSkipTokens() {
229         return EMPTY_TOKEN_ID_ARRAY;
230     }
231
232     /** Gets the token-id of the token at the given position.
233     * @param offset position at which the token should be returned
234     * @return token-id of the token at the requested position. If there's no more
235     * tokens in the text, the <tt>Syntax.INVALID</tt> is returned.
236     */

237     public TokenID getTokenID(int offset) throws BadLocationException JavaDoc {
238         FirstTokenTP fttp = new FirstTokenTP();
239         tokenizeText(fttp, offset, getDocument().getLength(), true);
240         return fttp.getTokenID();
241     }
242
243     /** Is the identifier at the position a function call?
244     * It first checks whether there is a identifier under
245     * the cursor and then it searches for the function call
246     * character - usually '('. Note: Java 1.5 annotations are not
247     * taken as function calls.
248     * @param identifierBlock int[2] block delimiting the identifier
249     * @return int[2] block or null if there's no function call
250     */

251     public int[] getFunctionBlock(int[] identifierBlock) throws BadLocationException JavaDoc {
252         if (identifierBlock != null) {
253             int nwPos = Utilities.getFirstNonWhiteFwd(getDocument(), identifierBlock[1]);
254             if ((nwPos >= 0) && (getDocument().getChars(nwPos, 1)[0] == '(')) {
255                 return new int[] { identifierBlock[0], nwPos + 1 };
256             }
257         }
258         return null;
259     }
260
261     public int[] getFunctionBlock(int offset) throws BadLocationException JavaDoc {
262         return getFunctionBlock(Utilities.getIdentifierBlock(getDocument(), offset));
263     }
264
265     public boolean isWhitespaceToken(TokenID tokenID,
266                                      char[] buffer, int offset, int tokenLength) {
267         return Analyzer.isWhitespace(buffer, offset, tokenLength);
268     }
269
270     public boolean isCommentOrWhitespace(int startPos, int endPos)
271     throws BadLocationException JavaDoc {
272         CommentOrWhitespaceTP tp= new CommentOrWhitespaceTP(getCommentTokens());
273         tokenizeText(tp, startPos, endPos, true);
274         return !tp.nonEmpty;
275     }
276
277     /** Gets the last non-blank and non-comment character on the given line.
278     */

279     public int getRowLastValidChar(int offset)
280     throws BadLocationException JavaDoc {
281         return Utilities.getRowLastNonWhite(getDocument(), offset);
282     }
283
284     /** Does the line contain some valid code besides of possible white space
285     * and comments?
286     */

287     public boolean isRowValid(int offset)
288     throws BadLocationException JavaDoc {
289         return Utilities.isRowWhite(getDocument(), offset);
290     }
291
292     /** Get the array of token IDs that denote the comments.
293     * Returns empty array by default.
294     */

295     public TokenID[] getCommentTokens() {
296         return EMPTY_TOKEN_ID_ARRAY;
297     }
298
299     /** Get the blocks consisting of comments in a specified document area.
300     * @param doc document to work with
301     * @param startPos starting position of the searched document area
302     * @param endPos ending position of the searched document area
303     */

304     public int[] getCommentBlocks(int startPos, int endPos)
305     throws BadLocationException JavaDoc {
306         return getTokenBlocks(startPos, endPos, getCommentTokens());
307     }
308
309     /** Find the type of the variable. The default behavior is to first
310     * search for the local variable declaration and then possibly for
311     * the global declaration and if the declaration position is found
312     * to get the first word on that position.
313     * @return it returns Object to enable the custom implementations
314     * to return the appropriate instances.
315     */

316     public Object JavaDoc findType(String JavaDoc varName, int varPos) {
317         Object JavaDoc type = null;
318         Map JavaDoc varMap = getLocalVariableMap(varPos); // first try local vars
319
if (varMap != null) {
320             type = varMap.get(varName);
321         }
322
323         if (type == null) {
324             varMap = getGlobalVariableMap(varPos); // try global vars
325
if (varMap != null) {
326                 type = varMap.get(varName);
327             }
328         }
329
330         return type;
331     }
332
333     public Map JavaDoc getLocalVariableMap(int offset) {
334         Integer JavaDoc posI = new Integer JavaDoc(offset);
335         Map JavaDoc varMap = (Map JavaDoc)localVarMaps.get(posI);
336         if (varMap == null) {
337             varMap = buildLocalVariableMap(offset);
338             localVarMaps.put(posI, varMap);
339         }
340         return varMap;
341     }
342
343     protected Map JavaDoc buildLocalVariableMap(int offset) {
344         int methodStartPos = getMethodStartPosition(offset);
345         if (methodStartPos >= 0 && methodStartPos < offset) {
346             VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(methodStartPos, offset);
347             try {
348                 tokenizeText(vmtp, methodStartPos, offset, true);
349                 return vmtp.getVariableMap();
350             } catch (BadLocationException JavaDoc e) {
351                 // will default null
352
}
353         }
354         return null;
355     }
356
357     public Map JavaDoc getGlobalVariableMap(int offset) {
358         Integer JavaDoc posI = new Integer JavaDoc(offset);
359         Map JavaDoc varMap = (Map JavaDoc)globalVarMaps.get(posI);
360         if (varMap == null) {
361             varMap = buildGlobalVariableMap(offset);
362             globalVarMaps.put(posI, varMap);
363         }
364         return varMap;
365     }
366
367     protected Map JavaDoc buildGlobalVariableMap(int offset) {
368         int docLen = getDocument().getLength();
369         VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(0, docLen);
370         if (vmtp != null) {
371             try {
372                 tokenizeText(vmtp, 0, docLen, true);
373                 return vmtp.getVariableMap();
374             } catch (BadLocationException JavaDoc e) {
375                 // will default null
376
}
377         }
378         return null;
379     }
380
381     /** Get the start position of the method or the area
382     * where the declaration can start.
383     */

384     protected int getMethodStartPosition(int offset) {
385         return 0; // return begining of the document by default
386
}
387
388     /** Find either the local or global declaration position. First
389     * try the local declaration and if it doesn't succeed, then
390     * try the global declaration.
391     */

392     public int findDeclarationPosition(String JavaDoc varName, int varPos) {
393         int offset = findLocalDeclarationPosition(varName, varPos);
394         if (offset < 0) {
395             offset = findGlobalDeclarationPosition(varName, varPos);
396         }
397         return offset;
398     }
399
400     public int findLocalDeclarationPosition(String JavaDoc varName, int varPos) {
401         int methodStartPos = getMethodStartPosition(varPos);
402         if (methodStartPos >= 0 && methodStartPos < varPos) {
403             return findDeclarationPositionImpl(varName, methodStartPos, varPos);
404         }
405         return -1;
406     }
407
408     /** Get the position of the global declaration of a given variable.
409     * By default it's implemented to use the same token processor as for the local
410     * variables but the whole file is searched.
411     */

412     public int findGlobalDeclarationPosition(String JavaDoc varName, int varPos) {
413         return findDeclarationPositionImpl(varName, 0, getDocument().getLength());
414     }
415
416     private int findDeclarationPositionImpl(String JavaDoc varName, int startPos, int endPos) {
417         DeclarationTokenProcessor dtp = createDeclarationTokenProcessor(varName, startPos, endPos);
418         if (dtp != null) {
419             try {
420                 tokenizeText(dtp, startPos, endPos, true);
421                 return dtp.getDeclarationPosition();
422             } catch (BadLocationException JavaDoc e) {
423                 // will default to -1
424
}
425         }
426         return -1;
427     }
428
429     protected DeclarationTokenProcessor createDeclarationTokenProcessor(
430         String JavaDoc varName, int startPos, int endPos) {
431         return null;
432     }
433
434     protected VariableMapTokenProcessor createVariableMapTokenProcessor(
435         int startPos, int endPos) {
436         return null;
437     }
438
439     
440     /** Check and possibly popup, hide or refresh the completion */
441     public int checkCompletion(JTextComponent JavaDoc target, String JavaDoc typedText, boolean visible ) {
442         return visible ? COMPLETION_HIDE : COMPLETION_CANCEL;
443     }
444
445     /** Token processor extended to get declaration position
446     * of the given variable.
447     */

448     public interface DeclarationTokenProcessor extends TokenProcessor {
449
450         /** Get the declaration position. */
451         public int getDeclarationPosition();
452
453     }
454
455     public interface VariableMapTokenProcessor extends TokenProcessor {
456
457         /** Get the map that contains the pairs [variable-name, variable-type]. */
458         public Map JavaDoc getVariableMap();
459
460     }
461
462     /** Finder for the matching bracket. It gets the original bracket char
463     * and searches for the appropriate matching bracket character.
464     */

465     public class BracketFinder extends FinderFactory.GenericFinder {
466
467         /** Original bracket char */
468         protected char bracketChar;
469
470         /** Matching bracket char */
471         protected char matchChar;
472
473         /** Depth of original brackets */
474         private int depth;
475
476         /** Will it be a forward finder +1 or backward finder -1 or 0 when
477         * the given character is not bracket character.
478         */

479         protected int moveCount;
480
481         /**
482         * @param bracketChar bracket char
483         */

484         public BracketFinder(char bracketChar) {
485             this.bracketChar = bracketChar;
486
487             updateStatus();
488
489             forward = (moveCount > 0);
490         }
491
492         /** Check whether the bracketChar really contains
493          * the bracket character. If so assign the matchChar
494          * and moveCount variables.
495          */

496         protected boolean updateStatus() {
497             boolean valid = true;
498             switch (bracketChar) {
499                 case '(':
500                     matchChar = ')';
501                     moveCount = +1;
502                     break;
503                 case ')':
504                     matchChar = '(';
505                     moveCount = -1;
506                     break;
507                 case '{':
508                     matchChar = '}';
509                     moveCount = +1;
510                     break;
511                 case '}':
512                     matchChar = '{';
513                     moveCount = -1;
514                     break;
515                 case '[':
516                     matchChar = ']';
517                     moveCount = +1;
518                     break;
519                 case ']':
520                     matchChar = '[';
521                     moveCount = -1;
522                     break;
523                 case '<':
524                     matchChar = '>';
525                     moveCount = +1;
526                     break;
527                 case '>':
528                     matchChar = '<';
529                     moveCount = -1;
530                     break;
531                 default:
532                     valid = false;
533             }
534             return valid;
535         }
536
537         protected int scan(char ch, boolean lastChar) {
538             if (ch == bracketChar) {
539                 depth++;
540             } else if (ch == matchChar) {
541                 if (--depth == 0) {
542                     found = true;
543                     return 0;
544                 }
545             }
546             return moveCount;
547         }
548
549     }
550
551     /** Create token-items */
552     final class TokenItemTP implements TokenProcessor {
553
554         private Item firstItem;
555
556         private Item lastItem;
557
558         private int fwdBatchLineCnt;
559         private int bwdBatchLineCnt;
560
561         private char[] buffer;
562
563         private int bufferStartPos;
564         
565         /** Target position corresponding to the begining of the token
566          * that is already chained if searching for backward tokens,
567          * or, the last token that should be scanned if searching
568          * in forward direction.
569          */

570         int targetOffset;
571
572
573         TokenItemTP() {
574             fwdBatchLineCnt = bwdBatchLineCnt = ((Integer JavaDoc)getDocument().getProperty(
575                                                      SettingsNames.LINE_BATCH_SIZE)).intValue();
576         }
577
578         public TokenItem getTokenChain() {
579             return firstItem;
580         }
581
582         public boolean token(TokenID tokenID, TokenContextPath tokenContextPath,
583         int tokenBufferOffset, int tokenLength) {
584             if (bufferStartPos + tokenBufferOffset >= targetOffset) { // stop scanning
585
return false;
586             }
587
588             lastItem = new Item(tokenID, tokenContextPath,
589                     bufferStartPos + tokenBufferOffset,
590                     new String JavaDoc(buffer, tokenBufferOffset, tokenLength), lastItem
591             );
592             
593             if (firstItem == null) { // not yet assigned
594
firstItem = lastItem;
595             }
596
597             return true;
598         }
599
600         public int eot(int offset) {
601             return ((Integer JavaDoc)getDocument().getProperty(SettingsNames.MARK_DISTANCE)).intValue();
602         }
603
604         public void nextBuffer(char[] buffer, int offset, int len,
605                                int startPos, int preScan, boolean lastBuffer) {
606             this.buffer = buffer;
607             bufferStartPos = startPos - offset;
608         }
609
610         Item getNextChunk(Item i) {
611             BaseDocument doc = getDocument();
612             int itemEndPos = i.getOffset() + i.getImage().length();
613             int docLen = doc.getLength();
614             if (itemEndPos == docLen) {
615                 return null;
616             }
617
618             int endPos;
619             try {
620                 endPos = Utilities.getRowStart(doc, itemEndPos, fwdBatchLineCnt);
621             } catch (BadLocationException JavaDoc e) {
622                 return null;
623             }
624
625             if (endPos == -1) { // past end of doc
626
endPos = docLen;
627             }
628             fwdBatchLineCnt *= 2; // larger batch in next call
629

630
631             Item nextChunkHead = null;
632             Item fit = firstItem;
633             Item lit = lastItem;
634             try {
635                 // Simulate initial conditions
636
firstItem = null;
637                 lastItem = null;
638                 targetOffset = endPos;
639
640                 tokenizeText(this, itemEndPos, endPos, false);
641                 nextChunkHead = firstItem;
642
643             } catch (BadLocationException JavaDoc e) {
644             } finally {
645                 // Link previous last with the current first
646
if (firstItem != null) {
647                     lit.next = firstItem;
648                     firstItem.previous = lit;
649                 }
650
651                 firstItem = fit;
652                 if (lastItem == null) { // restore in case of no token or crash
653
lastItem = lit;
654                 }
655             }
656
657             return nextChunkHead;
658         }
659
660         Item getPreviousChunk(Item i) {
661             BaseDocument doc = getDocument();
662             int itemStartPos = i.getOffset();
663             if (itemStartPos == 0) {
664                 return null;
665             }
666
667             int startPos;
668             try {
669                 startPos = Utilities.getRowStart(doc, itemStartPos, -bwdBatchLineCnt);
670             } catch (BadLocationException JavaDoc e) {
671                 return null;
672             }
673
674             if (startPos == -1) { // before begining of doc
675
startPos = 0;
676             }
677             bwdBatchLineCnt *= 2;
678
679             Item previousChunkLast = null;
680             Item fit = firstItem;
681             Item lit = lastItem;
682             try {
683                 // Simulate initial conditions
684
firstItem = null;
685                 lastItem = null;
686                 targetOffset = itemStartPos;
687
688                 tokenizeText(this, startPos, itemStartPos, false);
689                 previousChunkLast = lastItem;
690
691             } catch (BadLocationException JavaDoc e) {
692             } finally {
693                 // Link previous last
694
if (lastItem != null) {
695                     fit.previous = lastItem;
696                     lastItem.next = fit;
697                 }
698
699                 lastItem = lit;
700                 if (firstItem == null) { // restore in case of no token or crash
701
firstItem = fit;
702                 }
703             }
704
705             return previousChunkLast;
706         }
707
708         final class Item extends TokenItem.AbstractItem {
709
710             Item previous;
711
712             TokenItem next;
713
714             Item(TokenID tokenID, TokenContextPath tokenContextPath,
715             int offset, String JavaDoc image, Item previous) {
716                 super(tokenID, tokenContextPath, offset, image);
717                 if (previous != null) {
718                     this.previous = previous;
719                     previous.next = this;
720                 }
721             }
722
723             public TokenItem getNext() {
724                 if (next == null) {
725                     next = getNextChunk(this);
726                 }
727                 return next;
728             }
729
730             public TokenItem getPrevious() {
731                 if (previous == null) {
732                     previous = getPreviousChunk(this);
733                 }
734                 return previous;
735             }
736
737         }
738
739     }
740
741     /** Token processor that matches either the comments or whitespace */
742     class CommentOrWhitespaceTP implements TokenProcessor {
743
744         private char[] buffer;
745
746         private TokenID[] commentTokens;
747
748         boolean nonEmpty;
749
750         CommentOrWhitespaceTP(TokenID[] commentTokens) {
751             this.commentTokens = commentTokens;
752         }
753
754         public boolean token(TokenID tokenID, TokenContextPath tokenContextPath,
755         int offset, int tokenLength) {
756             for (int i = 0; i < commentTokens.length; i++) {
757                 if (tokenID == commentTokens[i]) {
758                     return true; // comment token found
759
}
760             }
761             boolean nonWS = isWhitespaceToken(tokenID, buffer, offset, tokenLength);
762             if (nonWS) {
763                 nonEmpty = true;
764             }
765             return nonWS;
766         }
767
768         public int eot(int offset) {
769             return 0;
770         }
771
772         public void nextBuffer(char[] buffer, int offset, int len,
773                                int startPos, int preScan, boolean lastBuffer) {
774             this.buffer = buffer;
775         }
776
777     }
778
779     static class FirstTokenTP implements TokenProcessor {
780
781         private TokenID tokenID;
782
783         public TokenID getTokenID() {
784             return tokenID;
785         }
786
787         public boolean token(TokenID tokenID, TokenContextPath tokenContextPath,
788         int offset, int tokenLen) {
789             this.tokenID = tokenID;
790             return false; // no more tokens
791
}
792
793         public int eot(int offset) {
794             return 0;
795         }
796
797         public void nextBuffer(char[] buffer, int offset, int len,
798                                int startPos, int preScan, boolean lastBuffer) {
799         }
800
801     }
802
803 }
804
Popular Tags