Source Code Cross Referenced for TokenMarker.java in  » Swing-Library » jEdit » org » gjt » sp » jedit » syntax » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jEdit » org.gjt.sp.jedit.syntax 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * TokenMarker.java - Tokenizes lines of text
003:         * :tabSize=8:indentSize=8:noTabs=false:
004:         * :folding=explicit:collapseFolds=1:
005:         *
006:         * Copyright (C) 1998, 2003 Slava Pestov
007:         * Copyright (C) 1999, 2000 mike dillon
008:         *
009:         * This program is free software; you can redistribute it and/or
010:         * modify it under the terms of the GNU General Public License
011:         * as published by the Free Software Foundation; either version 2
012:         * of the License, or any later version.
013:         *
014:         * This program is distributed in the hope that it will be useful,
015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017:         * GNU General Public License for more details.
018:         *
019:         * You should have received a copy of the GNU General Public License
020:         * along with this program; if not, write to the Free Software
021:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
022:         */
023:
024:        package org.gjt.sp.jedit.syntax;
025:
026:        //{{{ Imports
027:        import javax.swing.text.Segment;
028:        import java.util.*;
029:        import java.util.regex.Matcher;
030:        import java.util.regex.Pattern;
031:        import org.gjt.sp.jedit.TextUtilities;
032:        import org.gjt.sp.util.SegmentCharSequence;
033:        import org.gjt.sp.util.StandardUtilities;
034:
035:        //}}}
036:
037:        /**
038:         * A token marker splits lines of text into tokens. Each token carries
039:         * a length field and an identification tag that can be mapped to a color
040:         * or font style for painting that token.
041:         *
042:         * @author Slava Pestov, mike dillon
043:         * @version $Id: TokenMarker.java 11079 2007-11-16 03:20:00Z vanza $
044:         *
045:         * @see org.gjt.sp.jedit.syntax.Token
046:         * @see org.gjt.sp.jedit.syntax.TokenHandler
047:         */
048:        public class TokenMarker {
049:            //{{{ TokenMarker constructor
050:            public TokenMarker() {
051:            } //}}}
052:
053:            //{{{ addRuleSet() method
054:            public void addRuleSet(ParserRuleSet rules) {
055:                ruleSets.put(rules.getSetName(), rules);
056:
057:                if (rules.getSetName().equals("MAIN"))
058:                    mainRuleSet = rules;
059:            } //}}}
060:
061:            //{{{ getMainRuleSet() method
062:            public ParserRuleSet getMainRuleSet() {
063:                return mainRuleSet;
064:            } //}}}
065:
066:            //{{{ getRuleSet() method
067:            public ParserRuleSet getRuleSet(String setName) {
068:                return ruleSets.get(setName);
069:            } //}}}
070:
071:            //{{{ getRuleSets() method
072:            /**
073:             * @since jEdit 4.2pre3
074:             */
075:            public ParserRuleSet[] getRuleSets() {
076:                return ruleSets.values().toArray(
077:                        new ParserRuleSet[ruleSets.size()]);
078:            } //}}}
079:
080:            //{{{ markTokens() method
081:            /**
082:             * Do not call this method directly; call Buffer.markTokens() instead.
083:             *
084:             * @param prevContext the context of the previous line, it can be null
085:             * @param tokenHandler the token handler
086:             * @param line a segment containing the content of the line
087:             */
088:            public LineContext markTokens(LineContext prevContext,
089:                    TokenHandler tokenHandler, Segment line) {
090:                //{{{ Set up some instance variables
091:                // this is to avoid having to pass around lots and lots of
092:                // parameters.
093:                this .tokenHandler = tokenHandler;
094:                this .line = line;
095:
096:                lastOffset = line.offset;
097:                lineLength = line.count + line.offset;
098:
099:                context = new LineContext();
100:
101:                if (prevContext == null) {
102:                    context.rules = getMainRuleSet();
103:                    context.escapeRule = context.rules.getEscapeRule();
104:                } else {
105:                    context.parent = prevContext.parent;
106:                    context.setInRule(prevContext.inRule);
107:                    context.rules = prevContext.rules;
108:                    context.spanEndSubst = prevContext.spanEndSubst;
109:                }
110:
111:                keywords = context.rules.getKeywords();
112:
113:                seenWhitespaceEnd = false;
114:                whitespaceEnd = line.offset;
115:                //}}}
116:
117:                //{{{ Main parser loop
118:                int terminateChar = context.rules.getTerminateChar();
119:                boolean terminated = false;
120:                main_loop: for (pos = line.offset; pos < lineLength; pos++) {
121:                    //{{{ check if we have to stop parsing (happens if the terminateChar has been exceeded)
122:                    if (terminateChar >= 0
123:                            && pos - line.offset >= terminateChar
124:                            && !terminated) {
125:                        terminated = true;
126:                        context = new LineContext(
127:                                ParserRuleSet.getStandardRuleSet(context.rules
128:                                        .getDefault()), context);
129:                        keywords = context.rules.getKeywords();
130:                    } //}}}
131:
132:                    //{{{ Check for the escape rule before anything else.
133:                    if (context.escapeRule != null
134:                            && handleRule(context.escapeRule, false)) {
135:                        continue main_loop;
136:                    } //}}}
137:
138:                    //{{{ check for end of delegate
139:                    if (context.parent != null && context.parent.inRule != null
140:                            && checkDelegateEnd(context.parent.inRule)) {
141:                        seenWhitespaceEnd = true;
142:                        continue main_loop;
143:                    } //}}}
144:
145:                    //{{{ check every rule
146:                    Character ch = Character.valueOf(line.array[pos]);
147:                    List<ParserRule> rules = context.rules.getRules(ch);
148:                    for (ParserRule rule : rules) {
149:                        // stop checking rules if there was a match
150:                        if (handleRule(rule, false)) {
151:                            seenWhitespaceEnd = true;
152:                            continue main_loop;
153:                        }
154:                    } //}}}
155:
156:                    //{{{ check if current character is a word separator
157:                    if (Character.isWhitespace(ch)) {
158:                        if (!seenWhitespaceEnd)
159:                            whitespaceEnd = pos + 1;
160:
161:                        if (context.inRule != null)
162:                            handleRule(context.inRule, true);
163:
164:                        handleNoWordBreak();
165:
166:                        markKeyword(false);
167:
168:                        if (lastOffset != pos) {
169:                            tokenHandler.handleToken(line, context.rules
170:                                    .getDefault(), lastOffset - line.offset,
171:                                    pos - lastOffset, context);
172:                        }
173:
174:                        tokenHandler.handleToken(line, context.rules
175:                                .getDefault(), pos - line.offset, 1, context);
176:                        lastOffset = pos + 1;
177:                    } else {
178:                        if (keywords != null
179:                                || context.rules.getRuleCount() != 0) {
180:                            String noWordSep = context.rules.getNoWordSep();
181:
182:                            if (!Character.isLetterOrDigit(ch)
183:                                    && noWordSep.indexOf(ch) == -1) {
184:                                if (context.inRule != null)
185:                                    handleRule(context.inRule, true);
186:
187:                                handleNoWordBreak();
188:
189:                                markKeyword(true);
190:
191:                                tokenHandler.handleToken(line, context.rules
192:                                        .getDefault(),
193:                                        lastOffset - line.offset, 1, context);
194:                                lastOffset = pos + 1;
195:                            }
196:                        }
197:
198:                        seenWhitespaceEnd = true;
199:                    } //}}}
200:                } //}}}
201:
202:                //{{{ Mark all remaining characters
203:                pos = lineLength;
204:
205:                if (context.inRule != null)
206:                    handleRule(context.inRule, true);
207:
208:                handleNoWordBreak();
209:                markKeyword(true);
210:                //}}}
211:
212:                //{{{ Unwind any NO_LINE_BREAK parent delegates
213:                unwind: while (context.parent != null) {
214:                    ParserRule rule = context.parent.inRule;
215:                    if ((rule != null && (rule.action & ParserRule.NO_LINE_BREAK) == ParserRule.NO_LINE_BREAK)
216:                            || terminated) {
217:                        context = context.parent;
218:                        keywords = context.rules.getKeywords();
219:                        context.setInRule(null);
220:                    } else
221:                        break unwind;
222:                } //}}}
223:
224:                tokenHandler.handleToken(line, Token.END, pos - line.offset, 0,
225:                        context);
226:
227:                context = context.intern();
228:                tokenHandler.setLineContext(context);
229:
230:                /* for GC. */
231:                this .line = null;
232:
233:                return context;
234:            } //}}}
235:
236:            //{{{ Private members
237:
238:            //{{{ Instance variables
239:            private final Map<String, ParserRuleSet> ruleSets = new Hashtable<String, ParserRuleSet>(
240:                    64);
241:            private ParserRuleSet mainRuleSet;
242:
243:            // Instead of passing these around to each method, we just store them
244:            // as instance variables. Note that this is not thread-safe.
245:            private TokenHandler tokenHandler;
246:            /** The line from which we will mark the tokens. */
247:            private Segment line;
248:            /** The context of the current line. */
249:            private LineContext context;
250:            private KeywordMap keywords;
251:            private final Segment pattern = new Segment();
252:            private int lastOffset;
253:            private int lineLength;
254:            private int pos;
255:
256:            private int whitespaceEnd;
257:            private boolean seenWhitespaceEnd;
258:
259:            //}}}
260:
261:            //{{{ checkDelegateEnd() method
262:            private boolean checkDelegateEnd(ParserRule rule) {
263:                if (rule.end == null)
264:                    return false;
265:
266:                LineContext tempContext = context;
267:                context = context.parent;
268:                keywords = context.rules.getKeywords();
269:                boolean handled = handleRule(rule, true);
270:                context = tempContext;
271:                keywords = context.rules.getKeywords();
272:
273:                if (handled) {
274:                    if (context.inRule != null)
275:                        handleRule(context.inRule, true);
276:
277:                    markKeyword(true);
278:
279:                    context = (LineContext) context.parent.clone();
280:
281:                    tokenHandler.handleToken(line, matchToken(context.inRule,
282:                            context.inRule, context), pos - line.offset,
283:                            pattern.count, context);
284:
285:                    keywords = context.rules.getKeywords();
286:                    context.setInRule(null);
287:                    lastOffset = pos + pattern.count;
288:
289:                    // move pos to last character of match sequence
290:                    pos += pattern.count - 1;
291:
292:                    return true;
293:                }
294:
295:                return false;
296:            } //}}}
297:
298:            //{{{ handleRule() method
299:            /**
300:             * Checks if the rule matches the line at the current position
301:             * and handles the rule if it does match
302:             */
303:            private boolean handleRule(ParserRule checkRule, boolean end) {
304:                //{{{ Some rules can only match in certain locations
305:                if (!end) {
306:                    if (null == checkRule.upHashChars) {
307:                        if (checkRule.upHashChar != null
308:                                && (pos + checkRule.upHashChar.length() < line.array.length)
309:                                && !checkHashString(checkRule)) {
310:                            return false;
311:                        }
312:                    } else {
313:                        if (-1 == Arrays.binarySearch(checkRule.upHashChars,
314:                                Character.toUpperCase(line.array[pos]))) {
315:                            return false;
316:                        }
317:                    }
318:                }
319:
320:                int offset = (checkRule.action & ParserRule.MARK_PREVIOUS) != 0 ? lastOffset
321:                        : pos;
322:                int posMatch = end ? checkRule.endPosMatch
323:                        : checkRule.startPosMatch;
324:
325:                if ((posMatch & ParserRule.AT_LINE_START) == ParserRule.AT_LINE_START) {
326:                    if (offset != line.offset) {
327:                        return false;
328:                    }
329:                } else if ((posMatch & ParserRule.AT_WHITESPACE_END) == ParserRule.AT_WHITESPACE_END) {
330:                    if (offset != whitespaceEnd) {
331:                        return false;
332:                    }
333:                } else if ((posMatch & ParserRule.AT_WORD_START) == ParserRule.AT_WORD_START) {
334:                    if (offset != lastOffset) {
335:                        return false;
336:                    }
337:                } //}}}
338:
339:                int matchedChars = 1;
340:                CharSequence charSeq = null;
341:                Matcher match = null;
342:
343:                //{{{ See if the rule's start or end sequence matches here
344:                if (!end || (checkRule.action & ParserRule.MARK_FOLLOWING) == 0) {
345:                    // the end cannot be a regular expression
346:                    if ((checkRule.action & ParserRule.REGEXP) == 0 || end) {
347:                        if (end) {
348:                            if (context.spanEndSubst != null)
349:                                pattern.array = context.spanEndSubst;
350:                            else
351:                                pattern.array = checkRule.end;
352:                        } else
353:                            pattern.array = checkRule.start;
354:                        pattern.offset = 0;
355:                        pattern.count = pattern.array.length;
356:                        matchedChars = pattern.count;
357:
358:                        if (!SyntaxUtilities.regionMatches(context.rules
359:                                .getIgnoreCase(), line, pos, pattern.array)) {
360:                            return false;
361:                        }
362:                    } else {
363:                        // note that all regexps start with \A so they only
364:                        // match the start of the string
365:                        //int matchStart = pos - line.offset;
366:                        charSeq = new SegmentCharSequence(line, pos
367:                                - line.offset, line.count - (pos - line.offset));
368:                        match = checkRule.startRegexp.matcher(charSeq);
369:                        if (!match.lookingAt()) {
370:                            return false;
371:                        } else if (match.start() != 0) {
372:                            throw new InternalError("Can't happen");
373:                        } else {
374:                            matchedChars = match.end();
375:                            /* workaround for hang if match was
376:                             * zero-width. not sure if there is
377:                             * a better way to handle this */
378:                            if (matchedChars == 0)
379:                                matchedChars = 1;
380:                        }
381:                    }
382:                } //}}}
383:                //{{{ Check for an escape sequence
384:                if ((checkRule.action & ParserRule.IS_ESCAPE) == ParserRule.IS_ESCAPE) {
385:                    pos += pattern.count;
386:                } //}}}
387:                //{{{ Handle start of rule
388:                else if (!end) {
389:                    if (context.inRule != null)
390:                        handleRule(context.inRule, true);
391:
392:                    markKeyword((checkRule.action & ParserRule.MARK_PREVIOUS) != ParserRule.MARK_PREVIOUS);
393:
394:                    switch (checkRule.action & ParserRule.MAJOR_ACTIONS) {
395:                    //{{{ SEQ
396:                    case ParserRule.SEQ:
397:                        context.spanEndSubst = null;
398:
399:                        if ((checkRule.action & ParserRule.REGEXP) != 0) {
400:                            handleTokenWithSpaces(tokenHandler,
401:                                    checkRule.token, pos - line.offset,
402:                                    matchedChars, context);
403:                        } else {
404:                            tokenHandler.handleToken(line, checkRule.token, pos
405:                                    - line.offset, matchedChars, context);
406:                        }
407:
408:                        // a DELEGATE attribute on a SEQ changes the
409:                        // ruleset from the end of the SEQ onwards
410:                        if (checkRule.delegate != null) {
411:                            context = new LineContext(checkRule.delegate,
412:                                    context.parent);
413:                            keywords = context.rules.getKeywords();
414:                        }
415:                        break;
416:                    //}}}
417:                    //{{{ SPAN, EOL_SPAN
418:                    case ParserRule.SPAN:
419:                    case ParserRule.EOL_SPAN:
420:                        context.setInRule(checkRule);
421:
422:                        byte tokenType = matchToken(checkRule, context.inRule,
423:                                context);
424:
425:                        if ((checkRule.action & ParserRule.REGEXP) != 0) {
426:                            handleTokenWithSpaces(tokenHandler, tokenType, pos
427:                                    - line.offset, matchedChars, context);
428:                        } else {
429:                            tokenHandler.handleToken(line, tokenType, pos
430:                                    - line.offset, matchedChars, context);
431:                        }
432:
433:                        char[] spanEndSubst = null;
434:                        /* substitute result of matching the rule start
435:                         * into the end string.
436:                         *
437:                         * eg, in shell script mode, <<\s*(\w+) is
438:                         * matched into \<$1\> to construct rules for
439:                         * highlighting read-ins like this <<EOF
440:                         * ...
441:                         * EOF
442:                         */
443:                        if (charSeq != null && checkRule.end != null) {
444:                            spanEndSubst = substitute(match, checkRule.end);
445:                        }
446:
447:                        context.spanEndSubst = spanEndSubst;
448:                        context = new LineContext(checkRule.delegate, context);
449:                        keywords = context.rules.getKeywords();
450:
451:                        break;
452:                    //}}}
453:                    //{{{ MARK_FOLLOWING
454:                    case ParserRule.MARK_FOLLOWING:
455:                        tokenHandler.handleToken(line, matchToken(checkRule,
456:                                checkRule, context), pos - line.offset,
457:                                pattern.count, context);
458:
459:                        context.spanEndSubst = null;
460:                        context.setInRule(checkRule);
461:                        break;
462:                    //}}}
463:                    //{{{ MARK_PREVIOUS
464:                    case ParserRule.MARK_PREVIOUS:
465:                        context.spanEndSubst = null;
466:
467:                        if (pos != lastOffset) {
468:                            tokenHandler.handleToken(line, checkRule.token,
469:                                    lastOffset - line.offset, pos - lastOffset,
470:                                    context);
471:                        }
472:
473:                        tokenHandler.handleToken(line, matchToken(checkRule,
474:                                checkRule, context), pos - line.offset,
475:                                pattern.count, context);
476:
477:                        break;
478:                    //}}}
479:                    default:
480:                        throw new InternalError("Unhandled major action");
481:                    }
482:
483:                    // move pos to last character of match sequence
484:                    pos += matchedChars - 1;
485:                    lastOffset = pos + 1;
486:
487:                    // break out of inner for loop to check next char
488:                } //}}}
489:                //{{{ Handle end of MARK_FOLLOWING
490:                else if ((context.inRule.action & ParserRule.MARK_FOLLOWING) != 0) {
491:                    if (pos != lastOffset) {
492:                        tokenHandler.handleToken(line, context.inRule.token,
493:                                lastOffset - line.offset, pos - lastOffset,
494:                                context);
495:                    }
496:
497:                    lastOffset = pos;
498:                    context.setInRule(null);
499:                } //}}}
500:
501:                return true;
502:            } //}}}
503:
504:            //{{{ handleNoWordBreak() method
505:            private void handleNoWordBreak() {
506:                if (context.parent != null) {
507:                    ParserRule rule = context.parent.inRule;
508:                    if (rule != null
509:                            && (context.parent.inRule.action & ParserRule.NO_WORD_BREAK) != 0) {
510:                        if (pos != lastOffset) {
511:                            tokenHandler.handleToken(line, rule.token,
512:                                    lastOffset - line.offset, pos - lastOffset,
513:                                    context);
514:                        }
515:
516:                        lastOffset = pos;
517:                        context = context.parent;
518:                        keywords = context.rules.getKeywords();
519:                        context.setInRule(null);
520:                    }
521:                }
522:            } //}}}
523:
524:            //{{{ handleTokenWithSpaces() method
525:            private void handleTokenWithSpaces(TokenHandler tokenHandler,
526:                    byte tokenType, int start, int len, LineContext context) {
527:                int last = start;
528:                int end = start + len;
529:
530:                for (int i = start; i < end; i++) {
531:                    if (Character.isWhitespace(line.array[i + line.offset])) {
532:                        if (last != i) {
533:                            tokenHandler.handleToken(line, tokenType, last, i
534:                                    - last, context);
535:                        }
536:                        tokenHandler
537:                                .handleToken(line, tokenType, i, 1, context);
538:                        last = i + 1;
539:                    }
540:                }
541:
542:                if (last != end) {
543:                    tokenHandler.handleToken(line, tokenType, last, end - last,
544:                            context);
545:                }
546:            } //}}}
547:
548:            //{{{ markKeyword() method
549:            private void markKeyword(boolean addRemaining) {
550:                int len = pos - lastOffset;
551:                if (len == 0)
552:                    return;
553:
554:                //{{{ Do digits
555:                if (context.rules.getHighlightDigits()) {
556:                    boolean digit = false;
557:                    boolean mixed = false;
558:
559:                    for (int i = lastOffset; i < pos; i++) {
560:                        char ch = line.array[i];
561:                        if (Character.isDigit(ch))
562:                            digit = true;
563:                        else
564:                            mixed = true;
565:                    }
566:
567:                    if (mixed) {
568:                        Pattern digitRE = context.rules.getDigitRegexp();
569:
570:                        // only match against regexp if its not all
571:                        // digits; if all digits, no point matching
572:                        if (digit) {
573:                            if (digitRE == null) {
574:                                // mixed digit/alpha keyword,
575:                                // and no regexp... don't
576:                                // highlight as DIGIT
577:                                digit = false;
578:                            } else {
579:                                int oldCount = line.count;
580:                                int oldOffset = line.offset;
581:                                line.offset = lastOffset;
582:                                line.count = len;
583:                                CharSequence seq = new SegmentCharSequence(line);
584:                                digit = digitRE.matcher(seq).matches();
585:                                line.offset = oldOffset;
586:                                line.count = oldCount;
587:                            }
588:                        }
589:                    }
590:
591:                    if (digit) {
592:                        tokenHandler.handleToken(line, Token.DIGIT, lastOffset
593:                                - line.offset, len, context);
594:                        lastOffset = pos;
595:
596:                        return;
597:                    }
598:                } //}}}
599:
600:                //{{{ Do keywords
601:                if (keywords != null) {
602:                    byte id = keywords.lookup(line, lastOffset, len);
603:
604:                    if (id != Token.NULL) {
605:                        tokenHandler.handleToken(line, id, lastOffset
606:                                - line.offset, len, context);
607:                        lastOffset = pos;
608:                        return;
609:                    }
610:                } //}}}
611:
612:                //{{{ Handle any remaining crud
613:                if (addRemaining) {
614:                    tokenHandler.handleToken(line, context.rules.getDefault(),
615:                            lastOffset - line.offset, len, context);
616:                    lastOffset = pos;
617:                } //}}}
618:            } //}}}
619:
620:            //{{{ substitute() method
621:            private static char[] substitute(Matcher match, char[] end) {
622:                StringBuilder buf = new StringBuilder();
623:                for (int i = 0; i < end.length; i++) {
624:                    char ch = end[i];
625:                    if (ch == '$' || ch == '~') {
626:                        if (i == end.length - 1)
627:                            buf.append(ch);
628:                        else {
629:                            char digit = end[i + 1];
630:                            if (!Character.isDigit(digit))
631:                                buf.append(ch);
632:                            else if (ch == '$') {
633:                                buf.append(match.group(digit - '0'));
634:                                i++;
635:                            } else {
636:                                String s = match.group(digit - '0');
637:                                if (s.length() == 1) {
638:                                    char b = TextUtilities
639:                                            .getComplementaryBracket(s
640:                                                    .charAt(0), null);
641:                                    if (b == '\0')
642:                                        b = s.charAt(0);
643:                                    buf.append(b);
644:                                } else
645:                                    buf.append(ch);
646:                                i++;
647:                            }
648:                        }
649:                    } else
650:                        buf.append(ch);
651:                }
652:
653:                char[] returnValue = new char[buf.length()];
654:                buf.getChars(0, buf.length(), returnValue, 0);
655:                return returnValue;
656:            } //}}}
657:
658:            //{{{ matchToken() method
659:            private byte matchToken(ParserRule rule, ParserRule base,
660:                    LineContext ctx) {
661:                switch (rule.matchType) {
662:                case ParserRule.MATCH_TYPE_RULE:
663:                    return base.token;
664:
665:                case ParserRule.MATCH_TYPE_CONTEXT:
666:                    return context.rules.getDefault();
667:
668:                default:
669:                    return rule.matchType;
670:                }
671:            } //}}}
672:
673:            //{{{ checkHashString() method
674:            private boolean checkHashString(ParserRule rule) {
675:                for (int i = 0; i < rule.upHashChar.length(); i++) {
676:                    if (Character.toUpperCase(line.array[pos + i]) != rule.upHashChar
677:                            .charAt(i)) {
678:                        return false;
679:                    }
680:                }
681:                return true;
682:            } //}}}
683:
684:            //}}}
685:
686:            //{{{ LineContext class
687:            /**
688:             * Stores persistent per-line syntax parser state.
689:             */
690:            public static class LineContext {
691:                private static final Map<LineContext, LineContext> intern = new HashMap<LineContext, LineContext>();
692:
693:                public LineContext parent;
694:                public ParserRule inRule;
695:                public ParserRuleSet rules;
696:                // used for SPAN_REGEXP rules; otherwise null
697:                public char[] spanEndSubst;
698:                public ParserRule escapeRule;
699:
700:                //{{{ LineContext constructor
701:                public LineContext(ParserRuleSet rs, LineContext lc) {
702:                    rules = rs;
703:                    parent = (lc == null ? null : (LineContext) lc.clone());
704:                    /*
705:                     * SPANs with no delegate need to propagate the
706:                     * escape rule to the child context, so this is
707:                     * needed.
708:                     */
709:                    if (rs.getModeName() != null)
710:                        escapeRule = rules.getEscapeRule();
711:                    else
712:                        escapeRule = lc.escapeRule;
713:                } //}}}
714:
715:                //{{{ LineContext constructor
716:                public LineContext() {
717:                } //}}}
718:
719:                //{{{ intern() method
720:                public LineContext intern() {
721:                    LineContext obj = intern.get(this );
722:                    if (obj == null) {
723:                        intern.put(this , this );
724:                        return this ;
725:                    } else
726:                        return obj;
727:                } //}}}
728:
729:                //{{{ hashCode() method
730:                public int hashCode() {
731:                    if (inRule != null)
732:                        return inRule.hashCode();
733:                    else if (rules != null)
734:                        return rules.hashCode();
735:                    else
736:                        return 0;
737:                } //}}}
738:
739:                //{{{ equals() method
740:                public boolean equals(Object obj) {
741:                    if (obj instanceof  LineContext) {
742:                        LineContext lc = (LineContext) obj;
743:                        return lc.inRule == inRule
744:                                && lc.rules == rules
745:                                && StandardUtilities.objectsEqual(parent,
746:                                        lc.parent)
747:                                && charArraysEqual(spanEndSubst,
748:                                        lc.spanEndSubst);
749:                    } else
750:                        return false;
751:                } //}}}
752:
753:                //{{{ clone() method
754:                public Object clone() {
755:                    LineContext lc = new LineContext();
756:                    lc.inRule = inRule;
757:                    lc.rules = rules;
758:                    lc.parent = (parent == null) ? null : (LineContext) parent
759:                            .clone();
760:                    lc.spanEndSubst = spanEndSubst;
761:                    lc.escapeRule = escapeRule;
762:
763:                    return lc;
764:                } //}}}
765:
766:                //{{{ charArraysEqual() method
767:                private static boolean charArraysEqual(char[] c1, char[] c2) {
768:                    if (c1 == null)
769:                        return c2 == null;
770:
771:                    // c1 is not null
772:                    if (c2 == null)
773:                        return false;
774:
775:                    if (c1.length != c2.length)
776:                        return false;
777:
778:                    for (int i = 0; i < c1.length; i++) {
779:                        if (c1[i] != c2[i])
780:                            return false;
781:                    }
782:
783:                    return true;
784:                } //}}}
785:
786:                //{{{ setInRule() method
787:                /**
788:                 * Sets the current rule being processed and adjusts the
789:                 * escape rule for the context based on the rule.
790:                 */
791:                public void setInRule(ParserRule rule) {
792:                    inRule = rule;
793:                    if (rule != null && rule.escapeRule != null)
794:                        escapeRule = rule.escapeRule;
795:                    else if (rules != null && rules.getName() != null)
796:                        escapeRule = rules.getEscapeRule();
797:                    else if (parent != null)
798:                        escapeRule = parent.escapeRule;
799:                    else
800:                        escapeRule = null;
801:                } //}}}
802:
803:            } //}}}
804:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.