Source Code Cross Referenced for SourceMapExtractor.java in  » Parser » Rats-Parser-Generators » xtc » lang » 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 » Parser » Rats Parser Generators » xtc.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package xtc.lang;
002:
003:        import java.io.CharArrayWriter;
004:        import java.io.FileReader;
005:        import java.io.IOException;
006:        import java.io.LineNumberReader;
007:        import java.io.File;
008:        import java.io.PrintWriter;
009:        import java.util.HashMap;
010:        import java.util.regex.Matcher;
011:        import java.util.regex.Pattern;
012:        import java.util.TreeSet;
013:
014:        /**
015:         * A class to extract a line number mapping for a source-to-source
016:         * transformation. The "input source" and the "output source" are input and
017:         * output of the source-to-source transformation. For instance, Main.jni and
018:         * Main.java are input source and output source files in the Jeannie framework.
019:         * This source map extractor assumes that the output source file contains the
020:         * input source line directives in a "//#line ${lineno} ${source file} form, and
021:         * this form is similiar to the C line number directive.
022:         * 
023:         * The source map extractor takes an output source file (Main.java), and
024:         * produces a mapping from the input source files (Main.jni) to output source
025:         * file (Main.java) in JSR45 SMAP format. For more information, look at JSR45
026:         * [http://jcp.org/en/jsr/detail?id=45].
027:         * 
028:         * @author Byeongcheol Lee
029:         */
030:        public class SourceMapExtractor {
031:
032:            /**
033:             * A regular expression to recognize line number directive like the following.
034:             * 
035:             * //#line ${lineno} ${source file}
036:             */
037:            private static final Pattern lineDirectivePattern = Pattern
038:                    .compile("^\\s*//#line\\s+([0-9]+)\\s+\"(\\S+)\"$");
039:
040:            /**
041:             * Print a command line usage, and exit with an error code.
042:             * 
043:             * @param msg A user message to explain what was wrong.
044:             */
045:            private static void usage(String msg) {
046:                String umsg = "usage: SourceMapExtractor [source file]";
047:                System.err.println(umsg + "\n" + msg);
048:                System.exit(-1);
049:            }
050:
051:            /**
052:             * Drives printing the source remapping infomation for the given
053:             * #line-decorated source file.
054:             * 
055:             * @param args A command line arguments.
056:             */
057:            public static void main(String[] args) {
058:
059:                String outputSourceFileName = null;
060:
061:                // parse command line argument
062:                for (int i = 0; i < args.length; i++) {
063:                    String arg = args[i];
064:                    if (outputSourceFileName == null) {
065:                        outputSourceFileName = arg;
066:                    } else {
067:                        usage("can not recognize command line option:" + arg);
068:                    }
069:                }
070:
071:                // check outputSourceFileName is readable
072:                if (outputSourceFileName == null) {
073:                    usage("please, specify [java source file]");
074:                }
075:                File javaSourceFile = new File(outputSourceFileName);
076:                if (!javaSourceFile.isFile()) {
077:                    usage("can not find " + outputSourceFileName);
078:                }
079:                if (!javaSourceFile.canRead()) {
080:                    usage("check permission for reading "
081:                            + outputSourceFileName);
082:                }
083:
084:                try {
085:                    // read output source file to get source-to-source mapping
086:                    SourceMapExtractor smapgen = new SourceMapExtractor(
087:                            outputSourceFileName);
088:                    smapgen.genSMAP();
089:
090:                    // print the source-to-source map to standard output.
091:                    System.out.println(smapgen.toStringInSMAPFormat());
092:
093:                } catch (IOException ioe) {
094:                    System.err.println("failed in extracting SMAP from the "
095:                            + outputSourceFileName);
096:                }
097:            }
098:
099:            /**
100:             * The input source file.
101:             */
102:            final protected String sourceFile;
103:
104:            /**
105:             * The total number of lines in the source file.
106:             */
107:            protected int numSourceLines = 0;
108:
109:            /**
110:             * The line-to-line mapping from the input source file to the output source
111:             * file.
112:             */
113:            final protected TreeSet<SMAPLineEntry> smapLineEntries = new TreeSet<SMAPLineEntry>();
114:
115:            /**
116:             * The mapping from an inputSourceFile to its unique id. Here, the input
117:             * source files appear in the line directive.
118:             */
119:            final protected HashMap<String, Integer> inputSourceFile2id = new HashMap<String, Integer>();
120:
121:            /**
122:             * The number of input source files so far. This is to generate unique id for
123:             * new input file.
124:             */
125:            protected int numInputSourceFiles = 0;
126:
127:            /**
128:             * A reverse mapping from an output source line to an input source line in
129:             * case of a single input source file.
130:             */
131:            private int[] outputSourceLine2inputSourceLine;
132:
133:            /**
134:             * @param s An input source file.
135:             */
136:            public SourceMapExtractor(String s) {
137:                this .sourceFile = s;
138:            }
139:
140:            /**
141:             * @return A number of input source files in the source-to-source mapping.
142:             */
143:            public int getNumberOfInputSourceFiles() {
144:                return numInputSourceFiles;
145:            }
146:
147:            /**
148:             * Search for line number directive (//#line ...) to generate a
149:             * source-to-source mapping information.
150:             */
151:            public void genSMAP() throws IOException {
152:                FileReader freader = new FileReader(sourceFile);
153:                LineNumberReader lnr = new LineNumberReader(freader);
154:
155:                LineNumberDirective prevJNILineDirective = null;
156:                while (true) {
157:                    String line = lnr.readLine();
158:                    if (line == null) {
159:                        numSourceLines = lnr.getLineNumber();
160:                        // EOF
161:                        if (prevJNILineDirective != null) {
162:                            addJNISourceLine(prevJNILineDirective, lnr
163:                                    .getLineNumber());
164:                        }
165:                        break;
166:                    }
167:
168:                    // check the line is of the form: //#line ${line number} ${filename}
169:                    LineNumberDirective curJNILineDirective = checkJNILineNumberDirective(
170:                            line, lnr.getLineNumber());
171:                    if (curJNILineDirective == null) {
172:                        continue;
173:                    }
174:
175:                    // handle line directive: //#line ${line number} ${filename}
176:                    if (prevJNILineDirective != null) {
177:                        // flush the previous line number directive.
178:                        addJNISourceLine(prevJNILineDirective, lnr
179:                                .getLineNumber() - 1);
180:                    }
181:
182:                    prevJNILineDirective = curJNILineDirective;
183:                }
184:            }
185:
186:            /**
187:             * Check if the current line is line number directive. If this line is not a
188:             * line number directive, this method returns null. Otherwise, this method
189:             * returns a line number directive object.
190:             * 
191:             * @param line A line to be checked.
192:             * @param lineNumber The current java line where the line appears.
193:             * @return An line number directive object.
194:             */
195:            private LineNumberDirective checkJNILineNumberDirective(
196:                    String line, int lineNumber) {
197:                // try paring : //#line ${file name} ${line number}
198:                final Matcher m = lineDirectivePattern.matcher(line);
199:                if (!m.matches()) {
200:                    return null;
201:                }
202:
203:                assert (m.group(1).length() > 0) && (m.group(2).length() > 0);
204:
205:                int jniLineNumber = Integer.parseInt(m.group(1));
206:                String fileName = m.group(2);
207:                int fileID = ensureSourceFileID(fileName);
208:                LineNumberDirective directive = new LineNumberDirective(fileID,
209:                        jniLineNumber, lineNumber);
210:
211:                return directive;
212:            }
213:
214:            /**
215:             * Add a line-to-line mapping entry to the smapLineEntries table.
216:             * 
217:             * @param lineDirective A line number directive.
218:             * @param lineEnd The end line number that the lineDirective affects.
219:             */
220:            private void addJNISourceLine(
221:                    final LineNumberDirective lineDirective, final int lineEnd) {
222:
223:                final int javaBegin = lineDirective.outputSourceLineNumber + 1;
224:                final int count = lineEnd - javaBegin + 1;
225:                // non-empty java line
226:                assert (javaBegin > 0) && (lineEnd > 0) && (count >= 1);
227:
228:                final int jniLineStart = lineDirective.inputSurceLineNumber;
229:                final int jniFileID = lineDirective.sourceFileID;
230:
231:                SMAPLineEntry entry = new SMAPLineEntry(jniLineStart,
232:                        jniFileID, javaBegin, count);
233:
234:                smapLineEntries.add(entry);
235:            }
236:
237:            /**
238:             * Ensure the input source file id is present in the inputSourceFile2id table.
239:             * 
240:             * @param sourceFile A source file name.
241:             * @return A file identification number.
242:             */
243:            private int ensureSourceFileID(final String sourceFile) {
244:                int id;
245:
246:                if (inputSourceFile2id.containsKey(sourceFile)) {
247:                    id = inputSourceFile2id.get(sourceFile);
248:                } else {
249:                    numInputSourceFiles++;
250:                    id = numInputSourceFiles;
251:                    inputSourceFile2id.put(sourceFile, id);
252:                }
253:
254:                assert inputSourceFile2id.containsKey(sourceFile);
255:
256:                return id;
257:            }
258:
259:            /**
260:             * This routine returns a source file name that appeared in all the line
261:             * number directive. This routine is only for the -fatten option in the
262:             * ClassSOurceRemapper.
263:             * 
264:             * @return A source file name.
265:             */
266:            protected String getSingleSourceFileName() {
267:
268:                assert numInputSourceFiles == 1;
269:
270:                String singleJNIFile = null;
271:                for (final String jniFile : inputSourceFile2id.keySet()) {
272:                    singleJNIFile = jniFile;
273:                    break;
274:                }
275:
276:                return singleJNIFile;
277:            }
278:
279:            /**
280:             * Given output source line number (e.g. in Main.java), this routine returns a
281:             * corresponding input source line number (e.g. in Main.jni). This routine is
282:             * only for the -fatten option in the ClassSOurceRemapper.
283:             * 
284:             * @param sourceLineNumber An output source line number.
285:             * @return An input source line number.
286:             */
287:            protected int getSingleSourceLine(int sourceLineNumber) {
288:
289:                assert numInputSourceFiles == 1;
290:
291:                if (outputSourceLine2inputSourceLine == null) {
292:                    outputSourceLine2inputSourceLine = new int[numSourceLines + 1];
293:                    for (final SMAPLineEntry entry : smapLineEntries) {
294:                        int begin = entry.getOutputLineBegin();
295:                        int end = entry.getOutputLineEnd();
296:                        assert (begin >= 1) && (end >= begin);
297:                        for (int outputLine = begin; outputLine <= end; outputLine++) {
298:                            int inputLine = entry
299:                                    .getInputSourceLine(outputLine);
300:                            int oldInputLine = outputSourceLine2inputSourceLine[outputLine];
301:                            if (oldInputLine >= 1) {
302:                                // take minium if conflict
303:                                if (oldInputLine < inputLine) {
304:                                    outputSourceLine2inputSourceLine[outputLine] = inputLine;
305:                                }
306:                            } else {
307:                                // first time
308:                                outputSourceLine2inputSourceLine[outputLine] = inputLine;
309:                            }
310:                        }
311:                    }
312:                }
313:
314:                assert outputSourceLine2inputSourceLine != null;
315:                return outputSourceLine2inputSourceLine[sourceLineNumber];
316:            }
317:
318:            /**
319:             * Return the source-to-source information in SMAP (JSR45) format.
320:             * 
321:             * @return A text in SMAP format.
322:             */
323:            public String toStringInSMAPFormat() {
324:
325:                CharArrayWriter wa = new CharArrayWriter();
326:                PrintWriter w = new PrintWriter(wa);
327:                w.println("SMAP");
328:                w.println(sourceFile);
329:                w.println("JNI");
330:                w.println("*S JNI");
331:
332:                // list of jni source file name and id
333:                w.println("*F");
334:                for (final String fname : inputSourceFile2id.keySet()) {
335:                    int fid = inputSourceFile2id.get(fname);
336:                    w.println("" + fid + " " + fname);
337:                }
338:
339:                // list of JNI to java line number with the following format (JSR45)
340:                w.println("*L");
341:                for (final SMAPLineEntry jline : smapLineEntries) {
342:                    w.println(jline.toStringInSMAPFormat());
343:                }
344:
345:                w.println("*E");
346:                w.close();
347:
348:                return wa.toString();
349:            }
350:
351:            /**
352:             * A SMAP line mapping entry class.
353:             * 
354:             */
355:            private static final class SMAPLineEntry implements 
356:                    Comparable<SMAPLineEntry> {
357:
358:                /**
359:                 * These fields represent a partial continuous line number mapping from the
360:                 * input source files to the output source file. For futher information,
361:                 * look at JSR45.
362:                 */
363:                private final int inputStartLine;
364:
365:                private final int inputFileID;
366:
367:                private final int repeat;
368:
369:                private final int outputStartline;
370:
371:                private final int ouputLineIncrement;
372:
373:                /**
374:                 * @param inputLine A beginning input source line number.
375:                 * @param inputFileID An intput source file id number.
376:                 * @param outputLineStart A beginning output source line number.
377:                 * @param count A number of lines in the inputr source.
378:                 */
379:                SMAPLineEntry(int inputLine, int inputFileID,
380:                        int outputLineStart, int count) {
381:                    assert (inputLine >= 1) && (outputLineStart >= 1)
382:                            && (count > 0);
383:                    this .inputStartLine = inputLine;
384:                    this .inputFileID = inputFileID;
385:                    this .repeat = count;
386:                    this .outputStartline = outputLineStart;
387:                    this .ouputLineIncrement = 1;
388:                }
389:
390:                /**
391:                 * @return The beginning input source line number.
392:                 */
393:                private int getInputLineBegin() {
394:                    return inputStartLine;
395:                }
396:
397:                /**
398:                 * @return The ending input source line number.
399:                 */
400:                private int getInputLineEnd() {
401:                    return inputStartLine + repeat - 1;
402:                }
403:
404:                /**
405:                 * @return The beginning output source line number.
406:                 */
407:                private int getOutputLineBegin() {
408:                    return outputStartline;
409:                }
410:
411:                /**
412:                 * @return The end of output source line number.
413:                 */
414:                private int getOutputLineEnd() {
415:                    return outputStartline + repeat * ouputLineIncrement - 1;
416:                }
417:
418:                /**
419:                 * @param outputLine The line number of the output file.
420:                 * @return An line number of the input file.
421:                 */
422:                private int getInputSourceLine(int outputLine) {
423:                    assert (outputLine >= getOutputLineBegin())
424:                            && (outputLine <= getOutputLineEnd());
425:                    int jniLine = (outputLine - outputStartline)
426:                            / ouputLineIncrement + inputStartLine;
427:                    assert (jniLine >= inputStartLine)
428:                            && (jniLine <= getInputLineEnd());
429:                    return jniLine;
430:                }
431:
432:                /**
433:                 * @return A text in the SMAP format.
434:                 */
435:                private String toStringInSMAPFormat() {
436:                    StringBuffer sb = new StringBuffer();
437:
438:                    sb.append(inputStartLine);
439:                    sb.append("#").append(inputFileID);
440:                    if (repeat != 1) {
441:                        sb.append(",").append(repeat);
442:                    }
443:                    sb.append(":").append(outputStartline);
444:                    if (ouputLineIncrement != 1) {
445:                        sb.append(",").append(ouputLineIncrement);
446:                    }
447:
448:                    return sb.toString();
449:                }
450:
451:                /**
452:                 * Compare and Order smap entry by output source line number.
453:                 * 
454:                 * @param o2 A SMAP entry.
455:                 * @return An integer value to compare two SMAP entry.
456:                 */
457:                public int compareTo(SMAPLineEntry o2) {
458:                    if (inputFileID != o2.inputFileID) {
459:                        return inputFileID - o2.inputFileID;
460:                    } else {
461:                        if (outputStartline != o2.outputStartline) {
462:                            return outputStartline - o2.outputStartline;
463:                        } else {
464:                            return inputStartLine - o2.inputStartLine;
465:                        }
466:                    }
467:                }
468:            }
469:
470:            /**
471:             * A class to represent a line number directive event.
472:             */
473:            private static final class LineNumberDirective {
474:
475:                /**
476:                 * The output source file line number where this event happened.
477:                 */
478:                private final int outputSourceLineNumber;
479:
480:                /**
481:                 * The input source line number that appeared in the line number directive.
482:                 */
483:                private final int inputSurceLineNumber;
484:
485:                /**
486:                 * The id number for the input source file that appeared in the line number
487:                 * directive.
488:                 */
489:                private final int sourceFileID;
490:
491:                /**
492:                 * @param fid  The input source file id number.
493:                 * @param inline The input source line number.
494:                 * @param outline The outoput source line number.
495:                 */
496:                public LineNumberDirective(int fid, int inline, int outline) {
497:                    assert (fid > 0) & (inline > 0) & (outline > 0);
498:                    sourceFileID = fid;
499:                    inputSurceLineNumber = inline;
500:                    outputSourceLineNumber = outline;
501:                }
502:            }
503:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.