Source Code Cross Referenced for JavaSourceParser.java in  » Code-Analyzer » Java2Html » de » java2html » javasource » 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 » Code Analyzer » Java2Html » de.java2html.javasource 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package de.java2html.javasource;
0002:
0003:        import java.io.BufferedReader;
0004:        import java.io.File;
0005:        import java.io.FileReader;
0006:        import java.io.IOException;
0007:        import java.io.InputStream;
0008:        import java.io.InputStreamReader;
0009:        import java.io.Reader;
0010:        import java.io.StringReader;
0011:        import java.net.URL;
0012:        import java.util.Hashtable;
0013:        import java.util.StringTokenizer;
0014:
0015:        import de.java2html.options.JavaSourceConversionOptions;
0016:        import de.java2html.util.IoUtilities;
0017:
0018:        /**
0019:         * Parses raw text to a {@link de.java2html.javasource.JavaSource} object. The
0020:         * parser can not only handle grammatically correct Java source files but also
0021:         * code snippets.
0022:         * 
0023:         * <p>
0024:         * (Parsing is done in multiple steps starting with raw text where every
0025:         * character is classified as UNDEFINED and trying to find out more about it
0026:         * step by step. There are some state machines used for parsing. They are hand
0027:         * coded and quite complicated. The parser seems to be very stable, as I have
0028:         * not been reported a single bug now for about two years.)
0029:         * 
0030:         * <p>
0031:         * For questions, suggestions, bug-reports, enhancement-requests etc. I may be
0032:         * contacted at: <a href="mailto:markus@jave.de">markus@jave.de</a>
0033:         * 
0034:         * The Java2html home page is located at: <a href="http://www.java2html.de">
0035:         * http://www.java2html.de</a>
0036:         * 
0037:         * @author <a href="mailto:markus@jave.de">Markus Gebhard</a>
0038:         * 
0039:         * <code>Copyright (C) Markus Gebhard 2000-2003
0040:         * 
0041:         * This program is free software; you can redistribute it and/or
0042:         *  * modify it under the terms of the GNU General Public License
0043:         *  * as published by the Free Software Foundation; either version 2
0044:         *  * of the License, or (at your option) any later version.
0045:         * 
0046:         * This program is distributed in the hope that it will be useful,
0047:         *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0048:         *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0049:         *  * GNU General Public License for more details.
0050:         * 
0051:         * You should have received a copy of the GNU General Public License
0052:         *  * along with this program; if not, write to the Free Software
0053:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.</code>
0054:         */
0055:        public class JavaSourceParser {
0056:            /** The source code being converted */
0057:            private JavaSource source;
0058:
0059:            /** For faster access to source.getCode() */
0060:            private String sourceCode;
0061:
0062:            /** For faster access to source.getClassification() */
0063:            private JavaSourceType[] sourceTypes;
0064:
0065:            private JavaSourceConversionOptions options;
0066:
0067:            /** Delimiters for numeric values. */
0068:            private final static String NUM_DELIMITERS = " \t\n\r()[]{};:+-/\\*!?#%&|<>=^,";
0069:
0070:            /** Delimiters for finding data types and keywords. */
0071:            private final static String DELIMITERS = " \t\n\r()[]{};:.+-/\\*!?#%&|<>=^";
0072:
0073:            /** Characters automatically classified as being empty (type==BACKGROUND) */
0074:            private final static String EMPTY_STR = " \t\n\r\f";
0075:
0076:            private final static String[] PRIMITIVE_DATATYPES = { "boolean",
0077:                    "byte", "char", "double", "float", "int", "long", "short",
0078:                    "void" };
0079:
0080:            /*
0081:             * As defined by Java Language Specification SE §3,
0082:             */
0083:            private final static String[] JAVA_KEYWORDS = { "assert",
0084:                    "abstract", "default", "if", "private", "this", "do",
0085:                    "implements", "protected", "throw", "break", "import",
0086:                    "public", "throws", "else", "instanceof", "return",
0087:                    "transient", "case", "extends", "try", "catch", "final",
0088:                    "interface", "static", "finally", "strictfp", "volatile",
0089:                    "class", "native", "super", "while", "const", "for", "new",
0090:                    "strictfp", "switch", "continue", "goto", "package",
0091:                    "synchronized", "threadsafe", "null", "true", "false",
0092:                    //Enum keyword from JDK1.5 (TypeSafe Enums)
0093:                    "enum", "@interface" };
0094:
0095:            private final static String[] JAVADOC_KEYWORDS = { "@author",
0096:                    "@beaninfo", "@docRoot", "@deprecated", "@exception",
0097:                    "@link", "@param", "@return", "@see", "@serial",
0098:                    "@serialData", "@serialField", "@since", "@throws",
0099:                    "@version",
0100:                    //new in JDK1.4
0101:                    "@linkplain", "@inheritDoc", "@value",
0102:                    //from iDoclet
0103:                    "@pre", "@post", "@inv",
0104:                    //from disy
0105:                    "@published" };
0106:
0107:            /** Hashtables for fast access to JavaDoc keywords (tags) */
0108:            private static Hashtable tableJavaDocKeywords;
0109:
0110:            /** Hashtables for fast access to keywords */
0111:            private static Hashtable tableJavaKeywords;
0112:
0113:            /* States for the first state machine */
0114:            private final static short PARSESTATE_FINISHED = -1;
0115:            private final static short COD = 0; //CODE
0116:            private final static short CAC = 1; //CODE AWAIT COMMENT
0117:            private final static short CL = 2; //COMMENT LINE
0118:            private final static short CBJ1 = 3; //COMMENT BLOCK or COMMENT JAVADOC 1
0119:            private final static short CBJ2 = 4; //COMMENT BLOCK or COMMENT JAVADOC 1
0120:            private final static short CB = 5; //COMMENT BLOCK
0121:            private final static short CBA = 6; //COMMENT BLOCK AWAIT END
0122:            private final static short CJ = 7; //COMMENT JAVADOC
0123:            private final static short CJA = 8; //COMMENT JAVADOC AWAIT END
0124:            private final static short QU = 9; //QUOTE
0125:            private final static short QUA = 10; //QUOTE AWAIT \"
0126:            private final static short CH1 = 11; // 
0127:            private final static short CH2 = 12; // 
0128:            private final static short CH3 = 13; // 
0129:            private final static short CH4 = 14; // 
0130:            private final static short CH5 = 15; // 
0131:            private final static short CH6 = 16; // 
0132:
0133:            /* Additional states for the second state machine */
0134:            private final static short PARSESTATE_START = 0;
0135:            private final static short PARSESTATE_NEUTRAL = 1;
0136:            private final static short PARSESTATE_DA = 2;
0137:            private final static short PARSESTATE_NA = 3;
0138:            private final static short PARSESTATE_EXP = 4;
0139:            private final static short PARSESTATE_HEX = 5;
0140:            private final static short PARSESTATE_HIA = 6;
0141:
0142:            /** Counter for this and that (parseThree()?) */
0143:            private int counter;
0144:
0145:            /** EOT=End of text */
0146:            private final static char EOT = (char) -1;
0147:
0148:            /* State informations for state machine one */
0149:            private short parseState;
0150:            private int parseSourcePos;
0151:            private int parseTypePos;
0152:
0153:            public JavaSourceParser() {
0154:                this (JavaSourceConversionOptions.getDefault());
0155:            }
0156:
0157:            public JavaSourceParser(JavaSourceConversionOptions options) {
0158:                buildTables();
0159:                this .options = options;
0160:            }
0161:
0162:            /**
0163:             * Baut aus den statischen String-Arrays die Hashtabellen auf, mit denen die
0164:             * Keywords im Quelltext gesucht werden.
0165:             */
0166:            private synchronized void buildTables() {
0167:                if (tableJavaDocKeywords != null && tableJavaKeywords != null) {
0168:                    return;
0169:                }
0170:
0171:                tableJavaDocKeywords = new Hashtable(
0172:                        (int) (JAVADOC_KEYWORDS.length * 1.5));
0173:                for (int i = 0; i < JAVADOC_KEYWORDS.length; ++i) {
0174:                    tableJavaDocKeywords.put(JAVADOC_KEYWORDS[i],
0175:                            JAVADOC_KEYWORDS[i]);
0176:                }
0177:
0178:                tableJavaKeywords = new Hashtable(
0179:                        (int) (JAVA_KEYWORDS.length * 1.5));
0180:                for (int i = 0; i < JAVA_KEYWORDS.length; ++i) {
0181:                    tableJavaKeywords.put(JAVA_KEYWORDS[i], JAVA_KEYWORDS[i]);
0182:                }
0183:            }
0184:
0185:            private final static boolean isEmpty(char ch) {
0186:                return (EMPTY_STR.indexOf(ch) != -1);
0187:            }
0188:
0189:            private boolean isNumberDelimiter(char ch) {
0190:                return (NUM_DELIMITERS.indexOf(ch) != -1);
0191:            }
0192:
0193:            private final static int indexOf(char ch, String s, int start,
0194:                    int end) {
0195:                if (end < start)
0196:                    return -1;
0197:
0198:                for (int i = start; i <= end; ++i) {
0199:                    if (s.charAt(i) == ch)
0200:                        return i;
0201:                }
0202:
0203:                return -1;
0204:            }
0205:
0206:            //public void parse(){
0207:            //  sourceCode=source.getCode();
0208:            //  sourceTypes=new JavaSourceType[sourceCode.length()];
0209:            //  parseOne();
0210:            //  parseTwo();
0211:            //  parseThree();
0212:            //  source.setClassification(sourceTypes);
0213:            //}
0214:
0215:            public JavaSource parse(File file) throws IOException {
0216:                source = parse(new FileReader(file));
0217:                source.setFileName(file.getName());
0218:                return source;
0219:            }
0220:
0221:            public JavaSource parse(String rawText) {
0222:                if (rawText == null) {
0223:                    throw new NullPointerException();
0224:                }
0225:                try {
0226:                    return parse(new StringReader(rawText));
0227:                } catch (IOException e) {
0228:                    System.err
0229:                            .println("Unexpected exception while parsing raw text: "
0230:                                    + e);
0231:                    return new JavaSource("");
0232:                }
0233:            }
0234:
0235:            public JavaSource parse(URL url) throws IOException {
0236:                InputStream inputStream = null;
0237:                try {
0238:                    inputStream = url.openStream();
0239:                    return parse(inputStream);
0240:                } finally {
0241:                    IoUtilities.close(inputStream);
0242:                }
0243:            }
0244:
0245:            public JavaSource parse(InputStream stream) throws IOException {
0246:                return parse(new InputStreamReader(stream));
0247:            }
0248:
0249:            public JavaSource parse(Reader reader) throws IOException {
0250:                if (reader == null) {
0251:                    throw new IllegalArgumentException("reader may not be null");
0252:                }
0253:                try {
0254:                    sourceCode = readPlainSource(reader);
0255:                } finally {
0256:                    IoUtilities.close(reader);
0257:                }
0258:                replaceTabs();
0259:
0260:                sourceTypes = new JavaSourceType[sourceCode.length()];
0261:                source = new JavaSource(sourceCode);
0262:                source.setClassification(sourceTypes);
0263:
0264:                parseOne();
0265:                parseTwo();
0266:                parseThree();
0267:                parseFour();
0268:
0269:                doStatistics();
0270:
0271:                return source;
0272:            }
0273:
0274:            private void parseFour() {
0275:                boolean isInsideAnnotation = false;
0276:                for (int i = 0; i < sourceTypes.length; ++i) {
0277:                    if (!isInsideAnnotation
0278:                            && sourceTypes[i] == JavaSourceType.CODE
0279:                            && sourceCode.charAt(i) == '@') {
0280:                        isInsideAnnotation = true;
0281:                        sourceTypes[i] = JavaSourceType.ANNOTATION;
0282:                    } else if (isInsideAnnotation
0283:                            && sourceTypes[i] == JavaSourceType.CODE
0284:                            && (Character.isJavaIdentifierPart(sourceCode
0285:                                    .charAt(i)) || sourceCode.charAt(i) == '.')) {
0286:                        sourceTypes[i] = JavaSourceType.ANNOTATION;
0287:                    } else {
0288:                        isInsideAnnotation = false;
0289:                    }
0290:                }
0291:            }
0292:
0293:            /**
0294:             * Gathers statistical information from the source code. After parsing this
0295:             * is quite easy and maybe it is useful for others. lineCount is needed for
0296:             * the html converter.
0297:             */
0298:            private void doStatistics() {
0299:                int index = 0;
0300:                source.getStatistic().clear();
0301:                source.getStatistic().setCharacterCount(sourceCode.length());
0302:                int linesContainingAnything = 0;
0303:
0304:                if (sourceCode.length() == 0) {
0305:                    source.getStatistic().setLineCount(0);
0306:                } else {
0307:                    StringTokenizer st = new StringTokenizer(sourceCode,
0308:                            "\n\r", true);
0309:                    while (st.hasMoreTokens()) {
0310:                        String line = st.nextToken();
0311:
0312:                        if (line.charAt(0) == '\r') {
0313:                            ++index;
0314:                        } else if (line.charAt(0) == '\n') {
0315:                            ++index;
0316:                            source.getStatistic().setLineCount(
0317:                                    source.getStatistic().getLineCount() + 1);
0318:                        } else {
0319:                            ++linesContainingAnything;
0320:                            statistics(line, index);
0321:                            index += line.length();
0322:                        }
0323:                    }
0324:                    source.getStatistic().setLineCount(
0325:                            source.getStatistic().getLineCount() + 1);
0326:                }
0327:
0328:                //some empty lines without any were not counted
0329:                source.getStatistic().setEmptyLineCount(
0330:                        source.getStatistic().getLineCount()
0331:                                - linesContainingAnything);
0332:            }
0333:
0334:            private void statistics(String line, int start) {
0335:                if (line.length() > source.getStatistic().getMaxLineLength()) {
0336:                    source.getStatistic().setMaxLineLength(line.length());
0337:                }
0338:
0339:                int end = start + line.length();
0340:
0341:                boolean containsCode = false;
0342:                boolean containsComment = false;
0343:
0344:                for (int i = start; i < end; ++i) {
0345:                    if (sourceTypes[i] == JavaSourceType.CODE
0346:                            || sourceTypes[i] == JavaSourceType.KEYWORD
0347:                            || sourceTypes[i] == JavaSourceType.CODE_TYPE
0348:                            || sourceTypes[i] == JavaSourceType.CHAR_CONSTANT
0349:                            || sourceTypes[i] == JavaSourceType.NUM_CONSTANT) {
0350:                        containsCode = true;
0351:                        if (containsComment)
0352:                            break;
0353:                    } else if (sourceTypes[i] == JavaSourceType.COMMENT_BLOCK
0354:                            || sourceTypes[i] == JavaSourceType.COMMENT_LINE
0355:                            || sourceTypes[i] == JavaSourceType.JAVADOC
0356:                            || sourceTypes[i] == JavaSourceType.JAVADOC_KEYWORD) {
0357:                        containsComment = true;
0358:                        if (containsCode)
0359:                            break;
0360:                    }
0361:                }
0362:
0363:                if (containsCode)
0364:                    source.getStatistic().setCodeLineCount(
0365:                            source.getStatistic().getCodeLineCount() + 1);
0366:                if (containsComment)
0367:                    source.getStatistic().setCommentLineCount(
0368:                            source.getStatistic().getCommentLineCount() + 1);
0369:                if (!containsCode && !containsComment)
0370:                    source.getStatistic().setEmptyLineCount(
0371:                            source.getStatistic().getEmptyLineCount() + 1);
0372:            }
0373:
0374:            private String readPlainSource(Reader reader) throws IOException {
0375:                return readPlainSource(new BufferedReader(reader));
0376:            }
0377:
0378:            private String readPlainSource(BufferedReader reader)
0379:                    throws IOException {
0380:
0381:                StringBuffer sb = new StringBuffer();
0382:                String line;
0383:                while ((line = reader.readLine()) != null) {
0384:                    sb.append(line);
0385:                    sb.append("\r\n");
0386:                }
0387:                if (sb.length() > 0) {
0388:                    sb.setLength(sb.length() - 2);
0389:                }
0390:                return sb.toString();
0391:                //    while (true){
0392:                //      char[] buffer = new char[256];
0393:                //      int length = reader.read(buffer, 0 , 256);
0394:                //      if (length<=0){
0395:                //        break;
0396:                //      }
0397:                //      sb.append(buffer, 0, length);
0398:                //    }
0399:                //    //Newlines are converted to "\r\n" for compatibility with eclipse
0400:                // styledtext!!!
0401:                //    return NewLineNormalizer.normalize(sb.toString(), "\r\n");
0402:            }
0403:
0404:            /**
0405:             * Preprocessing: Replaces all tabs (\t) by 'tabs' space characters.
0406:             */
0407:            private void replaceTabs() {
0408:                char[] t = new char[options.getTabSize()];
0409:                for (int i = 0; i < options.getTabSize(); ++i) {
0410:                    t[i] = ' ';
0411:                }
0412:
0413:                StringBuffer sb = new StringBuffer(
0414:                        (int) (sourceCode.length() * 1.3));
0415:                for (int i = 0; i < sourceCode.length(); ++i) {
0416:                    char ch = sourceCode.charAt(i);
0417:                    if (ch == '\t') {
0418:                        sb.append(t);
0419:                    } else {
0420:                        sb.append(ch);
0421:                    }
0422:                }
0423:
0424:                sourceCode = sb.toString();
0425:            }
0426:
0427:            /**
0428:             * First step of parsing. All characters are classified 'UNDEFINED' and we
0429:             * try to divide this into: CODE, CHAR_CONSTANT, COMMENT_LINE, COMMENT_BLOCK,
0430:             * COMMENT_JAVADOC, BACKGROUND and QUOTE This is done by a quite complicate
0431:             * state machine.
0432:             */
0433:            private void parseOne() {
0434:                parseState = COD;
0435:                parseSourcePos = 0;
0436:                parseTypePos = 0;
0437:
0438:                while (parseState != PARSESTATE_FINISHED) {
0439:                    parseOneDo();
0440:                }
0441:            }
0442:
0443:            /**
0444:             * State-machine for classifying the code to: CODE, CHAR_CONSTANT,
0445:             * COMMENT_LINE, COMMENT_BLOCK, COMMENT_JAVADOC, BACKGROUND and QUOTE
0446:             * 
0447:             * Note: It works - don't ask me how! If you want to know more about it all
0448:             * you can do is taking a sheet of paper (or more) and a pencil and try to
0449:             * draw the state machine :-)
0450:             */
0451:            private void parseOneDo() {
0452:                char ch = EOT;
0453:                if (sourceCode.length() > parseSourcePos) {
0454:                    ch = sourceCode.charAt(parseSourcePos++);
0455:                }
0456:
0457:                switch (parseState) {
0458:                case COD:
0459:                    if (ch == EOT) {
0460:                        parseState = PARSESTATE_FINISHED;
0461:                        return;
0462:                    }
0463:                    if (ch == '/') {
0464:                        parseState = CAC;
0465:                        return;
0466:                    }
0467:                    if (ch == '"') {
0468:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0469:                        parseState = QU;
0470:                        return;
0471:                    }
0472:                    if (ch == '\'') {
0473:                        parseState = CH1;
0474:                        return;
0475:                    }
0476:                    if (isEmpty(ch)) {
0477:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0478:                        return;
0479:                    }
0480:
0481:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0482:                    return;
0483:                case CAC:
0484:                    if (ch == EOT) {
0485:                        parseState = PARSESTATE_FINISHED;
0486:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0487:                        return;
0488:                    }
0489:                    if (ch == '/') {
0490:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_LINE;
0491:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_LINE;
0492:                        parseState = CL;
0493:                        return;
0494:                    }
0495:                    if (ch == '*') {
0496:                        parseState = CBJ1;
0497:                        return;
0498:                    }
0499:                    if (isEmpty(ch)) {
0500:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0501:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0502:                        parseState = COD;
0503:                        return;
0504:                    }
0505:
0506:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0507:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0508:                    parseState = COD;
0509:                    return;
0510:                case CL:
0511:                    if (ch == EOT) {
0512:                        parseState = PARSESTATE_FINISHED;
0513:                        return;
0514:                    }
0515:                    if (ch == '\n' || ch == '\r') {
0516:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0517:                        //ggf. durch COMMENT_LINE ersetzen
0518:                        parseState = COD;
0519:                        return;
0520:                    }
0521:                    if (isEmpty(ch)) {
0522:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0523:                        return;
0524:                    }
0525:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_LINE;
0526:                    return;
0527:                case CB:
0528:                    if (ch == EOT) {
0529:                        parseState = PARSESTATE_FINISHED;
0530:                        return;
0531:                    }
0532:                    if (ch == '*') {
0533:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0534:                        parseState = CBA;
0535:                        return;
0536:                    }
0537:                    if (isEmpty(ch)) {
0538:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0539:                        return;
0540:                    }
0541:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0542:                    return;
0543:                case CBA:
0544:                    if (ch == EOT) {
0545:                        parseState = PARSESTATE_FINISHED;
0546:                        return;
0547:                    }
0548:                    if (ch == '/') {
0549:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0550:                        parseState = COD;
0551:                        return;
0552:                    }
0553:                    if (ch == '*') {
0554:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0555:                        parseState = CBA;
0556:                        return;
0557:                    }
0558:                    if (isEmpty(ch)) {
0559:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0560:                        parseState = CB;
0561:                        return;
0562:                    }
0563:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0564:                    parseState = CB;
0565:                    return;
0566:                case CJ:
0567:                    if (ch == EOT) {
0568:                        parseState = PARSESTATE_FINISHED;
0569:                        return;
0570:                    }
0571:                    if (ch == '*') {
0572:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0573:                        parseState = CJA;
0574:                        return;
0575:                    }
0576:                    if (isEmpty(ch)) {
0577:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0578:                        return;
0579:                    }
0580:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0581:                    return;
0582:                case CJA:
0583:                    if (ch == EOT) {
0584:                        parseState = PARSESTATE_FINISHED;
0585:                        return;
0586:                    }
0587:                    if (ch == '/') {
0588:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0589:                        parseState = COD;
0590:                        return;
0591:                    }
0592:                    if (ch == '*') {
0593:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0594:                        parseState = CJA;
0595:                        return;
0596:                    }
0597:                    if (isEmpty(ch)) {
0598:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0599:                        parseState = CJ;
0600:                        return;
0601:                    }
0602:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0603:                    parseState = CJ;
0604:                    return;
0605:                case QU:
0606:                    if (ch == EOT) {
0607:                        parseState = PARSESTATE_FINISHED;
0608:                        return;
0609:                    }
0610:                    if (ch == '"') {
0611:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0612:                        parseState = COD;
0613:                        return;
0614:                    }
0615:                    if (ch == '\\') {
0616:                        parseState = QUA;
0617:                        return;
0618:                    }
0619:                    if (isEmpty(ch)) {
0620:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0621:                        return;
0622:                    }
0623:
0624:                    sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0625:                    return;
0626:                case QUA:
0627:                    if (ch == EOT) {
0628:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0629:                        parseState = PARSESTATE_FINISHED;
0630:                        return;
0631:                    }
0632:                    if (ch == '\\') {
0633:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0634:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0635:                        parseState = QU; //This one has been changed from QUA to QU in 2.0
0636:                        return;
0637:                    }
0638:                    if (isEmpty(ch)) {
0639:                        sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0640:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0641:                        parseState = QU;
0642:                        return;
0643:                    }
0644:                    sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0645:                    sourceTypes[parseTypePos++] = JavaSourceType.STRING;
0646:                    parseState = QU;
0647:                    return;
0648:                case CBJ1:
0649:                    if (ch == EOT) {
0650:                        parseState = PARSESTATE_FINISHED;
0651:                        sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0652:                        sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0653:                        return;
0654:                    }
0655:                    if (ch == '*') {
0656:                        parseState = CBJ2;
0657:                        return;
0658:                    }
0659:                    if (isEmpty(ch)) {
0660:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0661:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0662:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0663:                        parseState = CB;
0664:                        return;
0665:                    }
0666:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0667:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0668:                    sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0669:                    parseState = CB;
0670:                    return;
0671:                case CBJ2:
0672:                    if (ch == EOT) {
0673:                        parseState = PARSESTATE_FINISHED;
0674:                        sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0675:                        sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0676:                        sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0677:                        return;
0678:                    }
0679:                    if (ch == '/') {
0680:                        parseState = COD;
0681:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0682:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0683:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0684:                        sourceTypes[parseTypePos++] = JavaSourceType.COMMENT_BLOCK;
0685:                        return;
0686:                    }
0687:                    if (isEmpty(ch)) {
0688:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0689:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0690:                        sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0691:                        sourceTypes[parseTypePos++] = JavaSourceType.BACKGROUND;
0692:                        parseState = CJ;
0693:                        return;
0694:                    }
0695:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0696:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0697:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0698:                    sourceTypes[parseTypePos++] = JavaSourceType.JAVADOC;
0699:                    parseState = CJ;
0700:                    return;
0701:                case CH1:
0702:                    if (ch == EOT) {
0703:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0704:                        parseState = PARSESTATE_FINISHED;
0705:                        return;
0706:                    }
0707:                    if (ch == '\\') {
0708:                        parseState = CH3;
0709:                        return;
0710:                    }
0711:                    parseState = CH2;
0712:                    return;
0713:                case CH2:
0714:                    if (ch == EOT) {
0715:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0716:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0717:                        parseState = PARSESTATE_FINISHED;
0718:                        return;
0719:                    }
0720:                    if (ch == '\'') {
0721:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0722:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0723:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0724:                        parseState = COD;
0725:                        return;
0726:                    }
0727:                    sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0728:                    sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0729:                    sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0730:                    parseState = COD;
0731:                    return;
0732:                case CH3:
0733:                    if (ch == EOT) {
0734:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0735:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0736:                        parseState = PARSESTATE_FINISHED;
0737:                        return;
0738:                    }
0739:                    if (ch == 'u') {
0740:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0741:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0742:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0743:                        parseState = CH5;
0744:                        return;
0745:                    }
0746:                    if (ch >= '1' && ch <= '9') {
0747:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0748:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0749:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0750:                        parseState = CH6;
0751:                        return;
0752:                    }
0753:                    parseState = CH4;
0754:                    return;
0755:                case CH4:
0756:                    if (ch == EOT) {
0757:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0758:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0759:                        sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0760:                        parseState = PARSESTATE_FINISHED;
0761:                        return;
0762:                    }
0763:                    if (ch == '\'') {
0764:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0765:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0766:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0767:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0768:                        parseState = COD;
0769:                        return;
0770:                    }
0771:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0772:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0773:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0774:                    sourceTypes[parseTypePos++] = JavaSourceType.CODE;
0775:                    parseState = COD;
0776:                    return;
0777:                case CH6:
0778:                    if (ch == EOT) {
0779:                        parseState = PARSESTATE_FINISHED;
0780:                        return;
0781:                    }
0782:                    if (ch == '\'') {
0783:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0784:                        parseState = COD;
0785:                        return;
0786:                    }
0787:                    if (ch >= '0' && ch <= '9') {
0788:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0789:                        return;
0790:                    }
0791:                    sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0792:                    parseState = COD;
0793:                    return;
0794:                case CH5:
0795:                    if (ch == EOT) {
0796:                        parseState = PARSESTATE_FINISHED;
0797:                        return;
0798:                    }
0799:                    if (ch == '\'') {
0800:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0801:                        parseState = COD;
0802:                        return;
0803:                    }
0804:                    if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')
0805:                            || (ch >= 'A' && ch <= 'F')) {
0806:                        sourceTypes[parseTypePos++] = JavaSourceType.CHAR_CONSTANT;
0807:                        return;
0808:                    }
0809:                    sourceTypes[parseTypePos++] = JavaSourceType.UNDEFINED;
0810:                    parseState = COD;
0811:                    return;
0812:                }
0813:            }
0814:
0815:            /**
0816:             * Second step for parsing. The categories from the first step are further
0817:             * divided: COMMENT_JAVADOC to COMMENT_JAVADOC and COMMENT_KEYWORD CODE to
0818:             * CODE, CODE_TYPE and CODE_KEYWORD
0819:             */
0820:            private void parseTwo() {
0821:                for (int index = 0; index < sourceTypes.length; ++index) {
0822:                    if (sourceTypes[index] == JavaSourceType.CODE) {
0823:                        if (isParenthesis(sourceCode.charAt(index))) {
0824:                            mark(index, JavaSourceType.PARENTHESIS);
0825:                        }
0826:                    }
0827:                }
0828:
0829:                int start = 0;
0830:                int end = 0;
0831:
0832:                while (end < sourceTypes.length - 1) {
0833:                    while (end < sourceTypes.length - 1
0834:                            && sourceTypes[end + 1] == sourceTypes[start])
0835:                        ++end;
0836:
0837:                    parseTwo(start, end);
0838:
0839:                    start = end + 1;
0840:                    end = start;
0841:                }
0842:            }
0843:
0844:            private boolean isParenthesis(char ch) {
0845:                return ch == '{' || ch == '}' || ch == '[' || ch == ']'
0846:                        || ch == '(' || ch == ')';
0847:            }
0848:
0849:            private void parseTwo(int start, int end) {
0850:                if (sourceTypes[start] == JavaSourceType.JAVADOC) {
0851:                    parseTwoCommentBlock(start, end);
0852:                    return;
0853:                } else if (sourceTypes[start] == JavaSourceType.CODE) {
0854:                    parseTwoCode(start, end);
0855:                    return;
0856:                }
0857:
0858:                //Keine weitere Unterteilung möglich
0859:                return;
0860:            }
0861:
0862:            /**
0863:             * Looks for primitive datatyes and keywords in the given region.
0864:             */
0865:            private void parseTwoCode(int start, int end) {
0866:                String code = sourceCode.substring(start, end + 1);
0867:
0868:                int index = start;
0869:                StringTokenizer st = new StringTokenizer(code, DELIMITERS, true);
0870:                while (st.hasMoreTokens()) {
0871:                    String s = st.nextToken();
0872:                    //    if (s.length()==1){
0873:                    //      char ch=s.charAt(0);
0874:                    //      if (ch=='{' || ch=='}' ||
0875:                    //          ch=='[' || ch==']' ||
0876:                    //          ch=='(' || ch==')'){
0877:                    //        mark(index, JavaSourceType.PARENTHESIS);
0878:                    //      }
0879:                    //      ++index;
0880:                    //    }else{
0881:                    //Keyword?
0882:                    if (tableJavaKeywords.containsKey(s)) {
0883:                        mark(index, index + s.length(), JavaSourceType.KEYWORD);
0884:                        if (s.equals("package")) {
0885:                            int i1 = sourceCode.indexOf(';', index + 1);
0886:                            if (i1 != -1) {
0887:                                source.getStatistic().setPackageName(
0888:                                        sourceCode.substring(
0889:                                                index + s.length(), i1).trim());
0890:                            }
0891:                        }
0892:                    } else {
0893:                        //Datatype?
0894:                        for (int i = 0; i < PRIMITIVE_DATATYPES.length; ++i) {
0895:                            if (s.equals(PRIMITIVE_DATATYPES[i])) {
0896:                                mark(index, index + s.length(),
0897:                                        JavaSourceType.CODE_TYPE);
0898:                                break;
0899:                            }
0900:                        }
0901:                    }
0902:                    index += s.length();
0903:                    //    }
0904:                }
0905:            }
0906:
0907:            /**
0908:             * Tries to find JavaDoc comment keywords and html tags @l
0909:             */
0910:            private void parseTwoCommentBlock(int start, int end) {
0911:                int i1 = indexOf('@', sourceCode, start, end);
0912:
0913:                while (i1 != -1 && i1 + 1 < end) {
0914:                    int i2 = i1 + 1;
0915:
0916:                    char ch = sourceCode.charAt(i2 + 1);
0917:                    while (i2 < end
0918:                            && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) {
0919:                        ch = sourceCode.charAt(++i2 + 1);
0920:                    }
0921:
0922:                    String s = sourceCode.substring(i1, i2 + 1);
0923:                    //s is likely to be a valid JavaDoc-Tag
0924:
0925:                    //      if ((s.equals("@link") || s.equals("@linkplain"))
0926:                    //        && sourceCode.charAt(i1 - 1) == '{'
0927:                    //        && start > 0) {
0928:                    //        mark(i1 - 1, i1 + 5, JavaSourceType.JAVADOC_LINKS);
0929:                    //      }
0930:                    //      else
0931:                    if (tableJavaDocKeywords.containsKey(s)) {
0932:                        mark(i1, i2 + 1, JavaSourceType.JAVADOC_KEYWORD);
0933:                    }
0934:
0935:                    i1 = indexOf('@', sourceCode, i2, end);
0936:                }
0937:
0938:                //find html tags
0939:                i1 = indexOf('<', sourceCode, start, end);
0940:                while (i1 != -1 && i1 + 1 < end) {
0941:                    int i2 = sourceCode.indexOf('>', i1 + 1);
0942:
0943:                    //    char ch=sourceCode.charAt(i2+1);
0944:                    //    while(i2<end && ch!='>'){
0945:                    //      ch=sourceCode.charAt(++i2+1);
0946:                    //    }
0947:                    if (i2 == -1) {
0948:                        i1 = -1;
0949:                        break;
0950:                    }
0951:                    if (hasTypeOrEmpty(sourceTypes, i1, i2 + 1,
0952:                            JavaSourceType.JAVADOC)) {
0953:                        mark(i1, i2 + 1, JavaSourceType.JAVADOC_HTML_TAG);
0954:                    }
0955:                    i1 = indexOf('<', sourceCode, i2, end);
0956:                }
0957:            }
0958:
0959:            private static boolean hasTypeOrEmpty(JavaSourceType[] sourceTypes,
0960:                    int startIndex, int endIndex, JavaSourceType javaSourceType) {
0961:
0962:                for (int i = startIndex; i <= endIndex; ++i) {
0963:                    if (!sourceTypes[i].equals(javaSourceType)
0964:                            && !sourceTypes[i]
0965:                                    .equals(JavaSourceType.BACKGROUND)) {
0966:                        return false;
0967:                    }
0968:                }
0969:                return true;
0970:            }
0971:
0972:            /**
0973:             * Third step for parsing: Finding number constants. CODE is further divided
0974:             * to CODE and NUM_CONSTANT
0975:             */
0976:            private void parseThree() {
0977:                int start = 0;
0978:                int end = 0;
0979:
0980:                while (end < sourceTypes.length - 1) {
0981:                    while (end < sourceTypes.length - 1
0982:                            && sourceTypes[end + 1] == sourceTypes[start]) {
0983:                        ++end;
0984:                    }
0985:
0986:                    if (sourceTypes[start] == JavaSourceType.CODE) {
0987:                        parseThree(start, end);
0988:                    }
0989:
0990:                    start = end + 1;
0991:                    end = start;
0992:                }
0993:
0994:                expandJavaDocLinks();
0995:            }
0996:
0997:            private void expandJavaDocLinks() {
0998:                expandEmbracedJavaDocTag("@link", JavaSourceType.JAVADOC_LINKS);
0999:                expandEmbracedJavaDocTag("@linkplain",
1000:                        JavaSourceType.JAVADOC_LINKS);
1001:            }
1002:
1003:            private void expandEmbracedJavaDocTag(String tag,
1004:                    JavaSourceType type) {
1005:                String pattern = "{" + tag;
1006:
1007:                for (int index = 0; index < sourceTypes.length; ++index) {
1008:                    int start = sourceCode.indexOf(pattern, index);
1009:                    if (start == -1) {
1010:                        break;
1011:                    }
1012:
1013:                    char ch = sourceCode.charAt(start + pattern.length());
1014:                    if (Character.isLetterOrDigit(ch)) {
1015:                        break;
1016:                    }
1017:
1018:                    if (!checkRegion(start + 1, start + 1 + tag.length() - 1,
1019:                            new IJavaSourceTypeChecker() {
1020:                                public boolean isValid(JavaSourceType type) {
1021:                                    return type
1022:                                            .equals(JavaSourceType.JAVADOC_KEYWORD);
1023:                                }
1024:                            })) {
1025:                        break;
1026:                    }
1027:
1028:                    int end = sourceCode.indexOf('}', start + pattern.length());
1029:                    if (end == -1) {
1030:                        break;
1031:                    }
1032:
1033:                    //Check region, can only be JavaDoc and Background
1034:                    if (checkRegion(start + 1 + tag.length(), end,
1035:                            new IJavaSourceTypeChecker() {
1036:                                public boolean isValid(JavaSourceType type) {
1037:                                    return type
1038:                                            .equals(JavaSourceType.BACKGROUND)
1039:                                            || type
1040:                                                    .equals(JavaSourceType.JAVADOC);
1041:                                }
1042:                            })) {
1043:                        markWithoutBackground(start, end, type);
1044:                    }
1045:                    index = end;
1046:                }
1047:
1048:            }
1049:
1050:            private boolean checkRegion(int start, int end,
1051:                    IJavaSourceTypeChecker checker) {
1052:                for (int i = start; i <= end; ++i) {
1053:                    if (!checker.isValid(sourceTypes[i])) {
1054:                        return false;
1055:                    }
1056:                }
1057:                return true;
1058:            }
1059:
1060:            private void markWithoutBackground(int start, int end,
1061:                    JavaSourceType type) {
1062:                for (int i = start; i <= end; ++i) {
1063:                    if (!sourceTypes[i].equals(JavaSourceType.BACKGROUND)) {
1064:                        sourceTypes[i] = type;
1065:                    }
1066:                }
1067:            }
1068:
1069:            /**
1070:             * Looks for number constants (NUM_CONSTANT) in the selected region.
1071:             */
1072:            private void parseThree(int start, int end) {
1073:                parseState = PARSESTATE_START;
1074:                parseSourcePos = start;
1075:                parseTypePos = start - 1;
1076:                counter = 0;
1077:
1078:                while (parseState != PARSESTATE_FINISHED) {
1079:                    parseThreeDo(end);
1080:                }
1081:            }
1082:
1083:            /**
1084:             * State-machine for NUM_CONSTANTs
1085:             */
1086:            private void parseThreeDo(int end) {
1087:                char ch = EOT;
1088:
1089:                if (parseSourcePos <= end)
1090:                    ch = sourceCode.charAt(parseSourcePos);
1091:
1092:                ++parseSourcePos;
1093:                ++parseTypePos;
1094:
1095:                switch (parseState) {
1096:                case PARSESTATE_START:
1097:                    if (ch == EOT) {
1098:                        parseState = PARSESTATE_FINISHED;
1099:                        return;
1100:                    }
1101:                    if (ch == '.') {
1102:                        ++counter;
1103:                        parseState = PARSESTATE_DA;
1104:                        return;
1105:                    }
1106:                    if (ch == '0') {
1107:                        ++counter;
1108:                        parseState = PARSESTATE_HIA;
1109:                        return;
1110:                    }
1111:                    if (ch >= '1' && ch <= '9') {
1112:                        ++counter;
1113:                        parseState = PARSESTATE_NA;
1114:                        return;
1115:                    }
1116:                    if (isNumberDelimiter(ch)) {
1117:                        //stay in this parse state
1118:                        return;
1119:                    }
1120:                    parseState = PARSESTATE_NEUTRAL;
1121:                    return;
1122:                case PARSESTATE_NEUTRAL:
1123:                    if (ch == EOT) {
1124:                        parseState = PARSESTATE_FINISHED;
1125:                        return;
1126:                    }
1127:                    if (isNumberDelimiter(ch)) {
1128:                        parseState = PARSESTATE_START;
1129:                        return;
1130:                    }
1131:                    return;
1132:                case PARSESTATE_DA:
1133:                    if (ch == EOT) {
1134:                        parseState = PARSESTATE_FINISHED;
1135:                        return;
1136:                    }
1137:                    if (ch >= '0' && ch <= '9') {
1138:                        ++counter;
1139:                        parseState = PARSESTATE_NA;
1140:                        return;
1141:                    }
1142:                    if (isNumberDelimiter(ch)) {
1143:                        parseState = PARSESTATE_START;
1144:                        counter = 0;
1145:                        return;
1146:                    }
1147:                    parseState = PARSESTATE_NEUTRAL;
1148:                    counter = 0;
1149:                    return;
1150:                case PARSESTATE_NA:
1151:                    if (ch == EOT) {
1152:                        parseState = PARSESTATE_FINISHED;
1153:                        mark(parseTypePos - counter, parseTypePos,
1154:                                JavaSourceType.NUM_CONSTANT);
1155:                        return;
1156:                    }
1157:                    if (ch == '.' || (ch >= '0' && ch <= '9')) {
1158:                        ++counter;
1159:                        return;
1160:                    }
1161:                    if (ch == 'e') {
1162:                        parseState = PARSESTATE_EXP;
1163:                        ++counter;
1164:                        return;
1165:                    }
1166:                    if (ch == 'f' || ch == 'F' || ch == 'd' || ch == 'D'
1167:                            || ch == 'l' || ch == 'L') {
1168:                        ++counter;
1169:                        mark(parseTypePos - counter + 1, parseTypePos + 1,
1170:                                JavaSourceType.NUM_CONSTANT);
1171:                        parseState = PARSESTATE_NEUTRAL;
1172:                        counter = 0;
1173:                        return;
1174:                    }
1175:                    if (isNumberDelimiter(ch)) {
1176:                        parseState = PARSESTATE_START;
1177:                        mark(parseTypePos - counter, parseTypePos,
1178:                                JavaSourceType.NUM_CONSTANT);
1179:                        counter = 0;
1180:                        return;
1181:                    }
1182:                    mark(parseTypePos - counter, parseTypePos,
1183:                            JavaSourceType.NUM_CONSTANT);
1184:                    parseState = PARSESTATE_NEUTRAL;
1185:                    counter = 0;
1186:                    return;
1187:                case PARSESTATE_HIA:
1188:                    if (ch == EOT) {
1189:                        parseState = PARSESTATE_FINISHED;
1190:                        mark(parseTypePos - counter, parseTypePos,
1191:                                JavaSourceType.NUM_CONSTANT);
1192:                        return;
1193:                    }
1194:                    if (ch == 'x' || ch == 'X') {
1195:                        parseState = PARSESTATE_HEX;
1196:                        ++counter;
1197:                        return;
1198:                    }
1199:                    if (ch == '.' || (ch >= '0' && ch <= '9')) {
1200:                        ++counter;
1201:                        parseState = PARSESTATE_NA;
1202:                        return;
1203:                    }
1204:                    if (ch == 'f' || ch == 'F' || ch == 'd' || ch == 'D'
1205:                            || ch == 'l' || ch == 'L') {
1206:                        ++counter;
1207:                        mark(parseTypePos - counter + 1, parseTypePos + 1,
1208:                                JavaSourceType.NUM_CONSTANT);
1209:                        parseState = PARSESTATE_NEUTRAL;
1210:                        counter = 0;
1211:                        return;
1212:                    }
1213:                    if (isNumberDelimiter(ch)) {
1214:                        parseState = PARSESTATE_START;
1215:                        mark(parseTypePos - counter, parseTypePos,
1216:                                JavaSourceType.NUM_CONSTANT);
1217:                        counter = 0;
1218:                        return;
1219:                    }
1220:                    mark(parseTypePos - counter, parseTypePos,
1221:                            JavaSourceType.NUM_CONSTANT);
1222:                    parseState = PARSESTATE_NEUTRAL;
1223:                    counter = 0;
1224:                    return;
1225:                case PARSESTATE_HEX:
1226:                    if (ch == EOT) {
1227:                        parseState = PARSESTATE_FINISHED;
1228:                        mark(parseTypePos - counter, parseTypePos,
1229:                                JavaSourceType.NUM_CONSTANT);
1230:                        return;
1231:                    }
1232:                    if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')
1233:                            || (ch >= 'A' && ch <= 'F')) {
1234:                        ++counter;
1235:                        parseState = PARSESTATE_HEX;
1236:                        return;
1237:                    }
1238:                    if (ch == 'l' || ch == 'L') {
1239:                        ++counter;
1240:                        mark(parseTypePos - counter + 1, parseTypePos + 1,
1241:                                JavaSourceType.NUM_CONSTANT);
1242:                        parseState = PARSESTATE_NEUTRAL;
1243:                        counter = 0;
1244:                        return;
1245:                    }
1246:                    if (isNumberDelimiter(ch)) {
1247:                        parseState = PARSESTATE_START;
1248:                        mark(parseTypePos - counter, parseTypePos,
1249:                                JavaSourceType.NUM_CONSTANT);
1250:                        counter = 0;
1251:                        return;
1252:                    }
1253:                    mark(parseTypePos - counter, parseTypePos,
1254:                            JavaSourceType.NUM_CONSTANT);
1255:                    parseState = PARSESTATE_NEUTRAL;
1256:                    counter = 0;
1257:                    return;
1258:                case PARSESTATE_EXP:
1259:                    if (ch == EOT) {
1260:                        parseState = PARSESTATE_FINISHED;
1261:                        mark(parseTypePos - counter, parseTypePos - 1,
1262:                                JavaSourceType.NUM_CONSTANT);
1263:                        return;
1264:                    }
1265:                    if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-') {
1266:                        ++counter;
1267:                        parseState = PARSESTATE_NA;
1268:                        return;
1269:                    }
1270:                    if (isNumberDelimiter(ch)) {
1271:                        parseState = PARSESTATE_START;
1272:                        mark(parseTypePos - counter, parseTypePos - 1,
1273:                                JavaSourceType.NUM_CONSTANT);
1274:                        counter = 0;
1275:                        return;
1276:                    }
1277:                    mark(parseTypePos - counter, parseTypePos - 1,
1278:                            JavaSourceType.NUM_CONSTANT);
1279:                    parseState = PARSESTATE_NEUTRAL;
1280:                    counter = 0;
1281:                    return;
1282:                }
1283:            }
1284:
1285:            /**
1286:             * Marks the specified region int the source code to the given type.
1287:             */
1288:            private void mark(int start, int endPlusOne, JavaSourceType type) {
1289:                for (int i = start; i < endPlusOne; ++i) {
1290:                    sourceTypes[i] = type;
1291:                }
1292:            }
1293:
1294:            /**
1295:             * Marks the character at the specified index to the given type.
1296:             */
1297:            private void mark(int index, JavaSourceType type) {
1298:                sourceTypes[index] = type;
1299:            }
1300:
1301:            //public static void main(String args[]){
1302:            //  JavaSource j=new JavaSource(new java.io.File("JavaSourceParser.java"));
1303:            //  
1304:            //  JavaSourceParser parser=new JavaSourceParser(j);
1305:            //  
1306:            //  parser.sourceCode=parser.source.getCode();
1307:            //  parser.sourceTypes=new byte[parser.sourceCode.length()];
1308:            //  
1309:            //  long time0=System.currentTimeMillis();
1310:            //  parser.parseOne();
1311:            //  long time1=System.currentTimeMillis();
1312:            //  parser.parseTwo();
1313:            //  long time2=System.currentTimeMillis();
1314:            //  parser.parseThree();
1315:            //  long time3=System.currentTimeMillis();
1316:            //  
1317:            //  System.out.println("Parse1: "+(time1-time0)+"ms");
1318:            //  System.out.println(" 2: "+(time2-time1)+"ms");
1319:            //  System.out.println(" 3: "+(time3-time2)+"ms");
1320:            //}
1321:
1322:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.