001: //
002: // Generated by JTB 1.2.1
003: //
004: package oscript.visitor;
005:
006: import oscript.syntaxtree.*;
007: import java.util.*;
008: import java.io.*;
009:
010: /**
011: * Dumps the syntax tree to a Writer using the location information in
012: * each NodeToken.
013: */
014: public class TreeDumper extends DepthFirstVisitor {
015: protected PrintWriter out;
016: private int curLine = 1;
017: private int curColumn = 1;
018: private boolean startAtNextToken = false;
019: private boolean printSpecials = true;
020:
021: /**
022: * The default constructor uses System.out as its output location.
023: * You may specify your own Writer or OutputStream using one of the
024: * other constructors.
025: */
026: public TreeDumper() {
027: out = new PrintWriter(System.out, true);
028: }
029:
030: public TreeDumper(Writer o) {
031: out = new PrintWriter(o, true);
032: }
033:
034: public TreeDumper(OutputStream o) {
035: out = new PrintWriter(o, true);
036: }
037:
038: /**
039: * Flushes the OutputStream or Writer that this TreeDumper is using.
040: */
041: public void flushWriter() {
042: out.flush();
043: }
044:
045: /**
046: * Allows you to specify whether or not to print special tokens.
047: */
048: public void printSpecials(boolean b) {
049: printSpecials = b;
050: }
051:
052: /**
053: * Starts the tree dumper on the line containing the next token
054: * visited. For example, if the next token begins on line 50 and the
055: * dumper is currently on line 1 of the file, it will set its current
056: * line to 50 and continue printing from there, as opposed to
057: * printing 49 blank lines and then printing the token.
058: */
059: public void startAtNextToken() {
060: startAtNextToken = true;
061: }
062:
063: /**
064: * Resets the position of the output "cursor" to the first line and
065: * column. When using a dumper on a syntax tree more than once, you
066: * either need to call this method or startAtNextToken() between each
067: * dump.
068: */
069: public void resetPosition() {
070: curLine = curColumn = 1;
071: }
072:
073: /**
074: * Dumps the current NodeToken to the output stream being used.
075: *
076: * @throws IllegalStateException if the token position is invalid
077: * relative to the current position, i.e. its location places it
078: * before the previous token.
079: */
080: public void visit(NodeToken n) {
081: if (n.beginLine == -1 || n.beginColumn == -1) {
082: printToken(n.tokenImage);
083: return;
084: }
085:
086: //
087: // Handle special tokens
088: //
089: if (printSpecials && n.numSpecials() > 0)
090: for (Enumeration e = n.specialTokens.elements(); e
091: .hasMoreElements();)
092: visit((NodeToken) e.nextElement());
093:
094: //
095: // Handle startAtNextToken option
096: //
097: if (startAtNextToken) {
098: curLine = n.beginLine;
099: curColumn = 1;
100: startAtNextToken = false;
101:
102: if (n.beginColumn < curColumn)
103: out.println();
104: }
105:
106: //
107: // Check for invalid token position relative to current position.
108: //
109: // if ( n.beginLine < curLine )
110: // throw new IllegalStateException("at token \"" + n.tokenImage +
111: // "\", n.beginLine = " + Integer.toString(n.beginLine) +
112: // ", curLine = " + Integer.toString(curLine));
113: // else if ( n.beginLine == curLine && n.beginColumn < curColumn )
114: // throw new IllegalStateException("at token \"" + n.tokenImage +
115: // "\", n.beginColumn = " +
116: // Integer.toString(n.beginColumn) + ", curColumn = " +
117: // Integer.toString(curColumn));
118:
119: //
120: // Move output "cursor" to proper location, then print the token
121: //
122: if (curLine < n.beginLine) {
123: curColumn = 1;
124: for (; curLine < n.beginLine; ++curLine)
125: out.println();
126: }
127:
128: for (; curColumn < n.beginColumn; ++curColumn)
129: out.print(" ");
130:
131: printToken(n.tokenImage);
132: }
133:
134: private void printToken(String s) {
135: if (s == null) {
136: out.print("<null>");
137: return;
138: }
139: for (int i = 0; i < s.length(); ++i) {
140: if (s.charAt(i) == '\n') {
141: ++curLine;
142: curColumn = 1;
143: } else
144: curColumn++;
145:
146: out.print(s.charAt(i));
147: }
148:
149: out.flush();
150: }
151: }
|