001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package xtc.tree;
020:
021: import java.io.PrintWriter;
022:
023: import java.util.Collection;
024: import java.util.Iterator;
025:
026: import xtc.Constants;
027:
028: import xtc.util.Utilities;
029:
030: /**
031: * A node pretty printing utility. This class provides a set of
032: * convenience methods to simplify the pretty printing of an abstract
033: * syntax tree.
034: *
035: * @author Robert Grimm
036: * @version $Revision: 1.2 $
037: */
038: public class Printer extends Utility {
039:
040: /** The length of the line separator. */
041: public static final int SEPARATOR_LENGTH = System.getProperty(
042: "line.separator").length();
043:
044: /** The print writer to print to. */
045: protected PrintWriter out;
046:
047: /** The current indentation level. */
048: protected int indent = 0;
049:
050: /**
051: * The number of characters printed by the most recently invoked
052: * method.
053: */
054: protected int printed = 0;
055:
056: // ========================================================================
057:
058: /**
059: * Create a new printer with the specified print writer.
060: *
061: * @param out The print writer to output to.
062: */
063: public Printer(PrintWriter out) {
064: this .out = out;
065: }
066:
067: // ========================================================================
068:
069: /**
070: * Increase the current indentation level.
071: *
072: * @return This printer.
073: */
074: public Printer incr() {
075: indent += Constants.INDENTATION;
076: return this ;
077: }
078:
079: /**
080: * Decrease the current indentation level.
081: *
082: * @return This printer.
083: */
084: public Printer decr() {
085: indent -= Constants.INDENTATION;
086: return this ;
087: }
088:
089: /**
090: * Indent.
091: *
092: * @return This printer.
093: */
094: public Printer indent() {
095: for (int i = 0; i < indent; i++) {
096: out.print(' ');
097: }
098:
099: printed = indent;
100: return this ;
101: }
102:
103: /**
104: * Indent one tab stop less than the current indentation level.
105: *
106: * @return This printer.
107: */
108: public Printer indentLess() {
109: int w = indent - Constants.INDENTATION;
110: if (0 > w) {
111: w = 0;
112: }
113:
114: for (int i = 0; i < w; i++) {
115: out.print(' ');
116: }
117:
118: printed = w;
119: return this ;
120: }
121:
122: // ========================================================================
123:
124: /**
125: * Print the specified character.
126: *
127: * @param c The character to print.
128: * @return This printer.
129: */
130: public Printer p(char c) {
131: out.print(c);
132: printed = 1;
133: return this ;
134: }
135:
136: /**
137: * Print the specified integer.
138: *
139: * @param i The integer to print.
140: * @return This printer.
141: */
142: public Printer p(int i) {
143: return p(Integer.toString(i));
144: }
145:
146: /**
147: * Print the specified string.
148: *
149: * @param s The string to print.
150: * @return This printer.
151: */
152: public Printer p(String s) {
153: out.print(s);
154: printed = s.length();
155: return this ;
156: }
157:
158: /**
159: * Print the specified character followed by a newline.
160: *
161: * @param c The character to print.
162: * @return This printer.
163: */
164: public Printer pln(char c) {
165: out.println(c);
166: printed = 1 + SEPARATOR_LENGTH;
167: return this ;
168: }
169:
170: /**
171: * Print the specified integer followed by a newline.
172: *
173: * @param i The integer to print.
174: * @return This printer.
175: */
176: public Printer pln(int i) {
177: return pln(Integer.toString(i));
178: }
179:
180: /**
181: * Print the specified string followed by a newline.
182: *
183: * @param s The string to print.
184: * @return This printer.
185: */
186: public Printer pln(String s) {
187: out.println(s);
188: printed = s.length() + SEPARATOR_LENGTH;
189: return this ;
190: }
191:
192: /**
193: * Print a newline.
194: *
195: * @return This printer.
196: */
197: public Printer pln() {
198: out.println();
199: printed = SEPARATOR_LENGTH;
200: return this ;
201: }
202:
203: // ========================================================================
204:
205: /**
206: * Print whitespace to align the output. This method prints
207: * whitespace to cover the difference between the specified number
208: * of printed characters and the specified alignment. If the number
209: * of characters already printed is equal or larger than the number
210: * of characters to align the output at, a single space character is
211: * printed.
212: *
213: * @param printed The number of characters already printed.
214: * @param alignment The number of characters to align at.
215: */
216: public Printer align(int printed, int alignment) {
217: int toPrint = alignment - printed;
218: if (0 >= toPrint)
219: toPrint = 1;
220: for (int i = 0; i < toPrint; i++) {
221: out.write(' ');
222: }
223: printed = toPrint;
224: return this ;
225: }
226:
227: /**
228: * Print whitespace to align the output. This method prints
229: * whitespace to cover the difference between the number of
230: * characters printed by the last invocation to any of this
231: * printer's methods (besides {@link #incr()} and {@link #decr()})
232: * and the specified alignment. If the number of characters already
233: * printed is equal or larger than the number of characters to align
234: * the output at, a single space character is printed.
235: *
236: * @param alignment The number of characters to align at.
237: */
238: public Printer align(int alignment) {
239: return align(printed, alignment);
240: }
241:
242: // ========================================================================
243:
244: /**
245: * Print the specified character with the specified escape sequences.
246: *
247: * @see Utilities
248: *
249: * @param c The character to print.
250: * @param flags The escape flags.
251: * @return This printer.
252: */
253: public Printer escape(char c, int flags) {
254: return p(Utilities.escape(c, flags));
255: }
256:
257: /**
258: * Print the specified string with the specified escape sequences.
259: *
260: * @see Utilities
261: *
262: * @param s The string to print.
263: * @param flags The escape flags.
264: * @return This printer.
265: */
266: public Printer escape(String s, int flags) {
267: return p(Utilities.escape(s, flags));
268: }
269:
270: // ========================================================================
271:
272: /**
273: * Print an indented separation comment.
274: *
275: * @return This printer.
276: */
277: public Printer sep() {
278: indent().p("// ");
279:
280: int n = 80 - indent - 3 - 3;
281: for (int i = 0; i < n; i++) {
282: out.print('=');
283: }
284:
285: out.println();
286: printed = 77 + SEPARATOR_LENGTH;
287: return this ;
288: }
289:
290: // ========================================================================
291:
292: /**
293: * Print the specified node. If the specified node is
294: * <code>null</code>, nothing is printed.
295: *
296: * @param node The node to print.
297: * @return This printer.
298: */
299: public Printer p(Node node) {
300: if (null != node)
301: node.accept(visitor());
302: return this ;
303: }
304:
305: /**
306: * Print the specified collection of nodes. Nodes are printed in the
307: * order of the collection's iterator. If the specified collection
308: * is <code>null</code>, nothing is printed.
309: *
310: * @param coll The collection of nodes to print.
311: * @return This printer.
312: */
313: public Printer p(Collection coll) {
314: if (null != coll) {
315: Iterator iter = coll.iterator();
316:
317: while (iter.hasNext()) {
318: p((Node) iter.next());
319: }
320: }
321: return this ;
322: }
323:
324: /**
325: * Print the specified collection of nodes. Nodes are printed in the
326: * order of the collection's iterator. If the specified collection
327: * is <code>null</code> or empty, nothing is printed.
328: *
329: * @param coll The collection of nodes to print.
330: * @param before The string to print before the nodes.
331: * @param sep The string to print between nodes.
332: */
333: public Printer p(Collection coll, String before, String sep) {
334: if (null != coll) {
335: boolean first = true;
336: Iterator iter = coll.iterator();
337:
338: while (iter.hasNext()) {
339: if (first) {
340: p(before);
341: first = false;
342: } else {
343: p(sep);
344: }
345: p((Node) iter.next());
346: }
347: }
348: return this ;
349: }
350:
351: // ========================================================================
352:
353: /**
354: * Print the original location for the specified node. Note that
355: * this method prints nothing.
356: *
357: * @param node The node.
358: * @return This printer.
359: */
360: public Printer loc(Node node) {
361: return this;
362: }
363:
364: }
|