001: package antlr;
002:
003: import java.io.OutputStream;
004: import java.io.PrintWriter;
005: import java.io.Writer;
006: import java.util.ArrayList;
007: import java.util.Collections;
008: import java.util.HashMap;
009: import java.util.Iterator;
010: import java.util.List;
011: import java.util.Map;
012:
013: // assumes one source file for now -- may need to change if ANTLR allows
014: // file inclusion in the future
015: // TODO optimize the output using line ranges for input/output files
016: // currently this writes one mapping per line
017: public class PrintWriterWithSMAP extends PrintWriter {
018: private int currentOutputLine = 1;
019: private int currentSourceLine = 0;
020: private Map sourceMap = new HashMap();
021:
022: private boolean lastPrintCharacterWasCR = false;
023: private boolean mapLines = false;
024: private boolean mapSingleSourceLine = false;
025: private boolean anythingWrittenSinceMapping = false;
026:
027: public PrintWriterWithSMAP(OutputStream out) {
028: super (out);
029: }
030:
031: public PrintWriterWithSMAP(OutputStream out, boolean autoFlush) {
032: super (out, autoFlush);
033: }
034:
035: public PrintWriterWithSMAP(Writer out) {
036: super (out);
037: }
038:
039: public PrintWriterWithSMAP(Writer out, boolean autoFlush) {
040: super (out, autoFlush);
041: }
042:
043: public void startMapping(int sourceLine) {
044: mapLines = true;
045: if (sourceLine != JavaCodeGenerator.CONTINUE_LAST_MAPPING)
046: currentSourceLine = sourceLine;
047: }
048:
049: public void startSingleSourceLineMapping(int sourceLine) {
050: mapSingleSourceLine = true;
051: mapLines = true;
052: if (sourceLine != JavaCodeGenerator.CONTINUE_LAST_MAPPING)
053: currentSourceLine = sourceLine;
054: }
055:
056: public void endMapping() {
057: mapLine(false);
058: mapLines = false;
059: mapSingleSourceLine = false;
060: }
061:
062: protected void mapLine(boolean incrementOutputLineCount) {
063: if (mapLines && anythingWrittenSinceMapping) {
064: Integer sourceLine = new Integer(currentSourceLine);
065: Integer outputLine = new Integer(currentOutputLine);
066: List outputLines = (List) sourceMap.get(sourceLine);
067: if (outputLines == null) {
068: outputLines = new ArrayList();
069: sourceMap.put(sourceLine, outputLines);
070: }
071: if (!outputLines.contains(outputLine))
072: outputLines.add(outputLine);
073: }
074: if (incrementOutputLineCount)
075: currentOutputLine++;
076: if (!mapSingleSourceLine)
077: currentSourceLine++;
078: anythingWrittenSinceMapping = false;
079: }
080:
081: public void dump(PrintWriter smapWriter, String targetClassName,
082: String grammarFile) {
083: smapWriter.println("SMAP");
084: smapWriter.println(targetClassName + ".java");
085: smapWriter.println("G");
086: smapWriter.println("*S G");
087: smapWriter.println("*F");
088: smapWriter.println("+ 0 " + grammarFile);
089: smapWriter.println(grammarFile);
090: smapWriter.println("*L");
091: List sortedSourceLines = new ArrayList(sourceMap.keySet());
092: Collections.sort(sortedSourceLines);
093: for (Iterator i = sortedSourceLines.iterator(); i.hasNext();) {
094: Integer sourceLine = (Integer) i.next();
095: List outputLines = (List) sourceMap.get(sourceLine);
096: for (Iterator j = outputLines.iterator(); j.hasNext();) {
097: Integer outputLine = (Integer) j.next();
098: smapWriter.println(sourceLine + ":" + outputLine);
099: }
100: }
101: smapWriter.println("*E");
102: smapWriter.close();
103: }
104:
105: public void write(char[] buf, int off, int len) {
106: int stop = off + len;
107: for (int i = off; i < stop; i++) {
108: checkChar(buf[i]);
109: }
110: super .write(buf, off, len);
111: }
112:
113: // after testing, may want to inline this
114: public void checkChar(int c) {
115: if (lastPrintCharacterWasCR && c != '\n')
116: mapLine(true);
117:
118: else if (c == '\n')
119: mapLine(true);
120:
121: else if (!Character.isWhitespace((char) c))
122: anythingWrittenSinceMapping = true;
123:
124: lastPrintCharacterWasCR = (c == '\r');
125: }
126:
127: public void write(int c) {
128: checkChar(c);
129: super .write(c);
130: }
131:
132: public void write(String s, int off, int len) {
133: int stop = off + len;
134: for (int i = off; i < stop; i++) {
135: checkChar(s.charAt(i));
136: }
137: super .write(s, off, len);
138: }
139:
140: // PrintWriter delegates write(char[]) to write(char[], int, int)
141: // PrintWriter delegates write(String) to write(String, int, int)
142:
143: // dependent on current impl of PrintWriter, which directly
144: // dumps a newline sequence to the target file w/o going through
145: // the other write methods.
146: public void println() {
147: mapLine(true);
148: super .println();
149: lastPrintCharacterWasCR = false;
150: }
151:
152: public Map getSourceMap() {
153: return sourceMap;
154: }
155:
156: public int getCurrentOutputLine() {
157: return currentOutputLine;
158: }
159: }
|