/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package cb.parser; import java.io.PrintStream; import java.util.Collection; import java.util.Iterator; import java.util.Stack; import cb.petal.BooleanLiteral; import cb.petal.DescendingVisitor; import cb.petal.FloatLiteral; import cb.petal.IntegerLiteral; import cb.petal.List; import cb.petal.Location; import cb.petal.PetalFile; import cb.petal.PetalNode; import cb.petal.PetalObject; import cb.petal.StringLiteral; import cb.petal.Tag; import cb.petal.Tagged; import cb.petal.Tuple; import cb.petal.Value; /** * Print petal file exactly like Rose would with some limitations concerning indendattion, i.e., if you don't mind white space, input and * output files are identical. * * @version $Id: PrintVisitor.java,v 1.3 2011/09/12 11:47:21 gpolet Exp $ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */ public class PrintVisitor extends DescendingVisitor { private PrintStream out; private int level = 0; private int column = 0, row = 1; private Stack align_stack = new Stack(); public PrintVisitor(PrintStream out) { this.out = out; } @Override public void visit(PetalFile obj) { println(); obj.getPetal().accept(this); println(); println(); obj.getDesign().accept(this); println(); } @Override public void visitObject(PetalObject obj) { StringBuffer buf = new StringBuffer("(object " + obj.getName()); for (Iterator i = obj.getParameterList().iterator(); i.hasNext();) { buf.append(" \"" + i.next() + "\""); } if (obj instanceof Tagged) { int label = ((Tagged) obj).getTag(); if (label > 0) { buf.append(" @" + label); } } print(buf); if (obj.getNames().size() > 0) { println(); } level++; setAlignment(obj.getLongestName().length()); for (Iterator i = obj.getNames().iterator(), j = obj.getPropertyList().iterator(); i.hasNext();) { indent(); print(i.next()); align(); ((PetalNode) j.next()).accept(this); if (i.hasNext()) { println(); } } print(")"); level--; restoreAlignment(); } /* Property names are aligned to a 4 column boundary * Property values are aligned to a 8 column boundary * 8 spaces are replaced by one tab. */ private int align_at = -1; private void setAlignment(int max) { align_stack.push(new Integer(align_at)); int indent = level * 4; int min_dist; // min distance between first char of name and first char of property if (indent % 8 == 0) { min_dist = 16; } else { // name aligned on 4 min_dist = 12; } align_at = indent + min_dist; } private void restoreAlignment() { Integer i = (Integer) align_stack.pop(); align_at = i.intValue(); } /** * Insert spaces up to next 8 column boundary */ private void align() { int fill; if (column < align_at) { fill = align_at - column; // System.err.println("< : " + align_at + ":" + column + ":" + fill); } else { fill = 8 - column % 8; // System.err.println(">= : " + align_at + ":" + column + ":" + fill); } int spaces = 4 - fill % 4; for (int i = 0; i < spaces; i++) { out.print(' '); } column += spaces; fill -= spaces; if (fill > 0) { int tabs = fill / 8; if (fill % 8 > 0) { tabs++; } for (int i = 0; i < tabs; i++) { out.print('\t'); } } // for(int i=0; i < fill; i++) // out.print(' '); column += fill; } /** * Initial indentation of line depend on current nesting level to 4 column boundary. */ private void indent() { int tabs = level / 2; // 4 spaces (INDENT) == 1 tab int spaces = level % 2; for (int i = 0; i < tabs; i++) { out.print('\t'); } for (int i = 0; i < spaces; i++) { out.print(" "); } column += level * 4; } private void println() { out.print("\r\n"); row++; column = 0; } private void print(java.lang.Object o) { String s = o.toString(); column += s.length(); out.print(s); } @Override public void visit(StringLiteral obj) { if (obj.isMultiLine()) { println(); Collection c = obj.getLines(); for (Iterator i = c.iterator(); i.hasNext();) { print("|" + i.next()); println(); } indent(); } else { print(obj); } } @Override public void visit(BooleanLiteral obj) { print(obj); } @Override public void visit(FloatLiteral obj) { print(obj); } @Override public void visit(IntegerLiteral obj) { print(obj); } @Override public void visit(Tag ref) { print(ref); } @Override public void visit(Location loc) { print(loc); } @Override public void visit(List list) { print("(list "); if (list.getName() != null) { print(list.getName()); } java.util.List c = list.getElements(); if (c.size() > 0) { level++; for (Iterator i = c.iterator(); i.hasNext();) { println(); indent(); ((PetalNode) i.next()).accept(this); } level--; } print(")"); } @Override public void visit(Value value) { print("(value " + value.getValueName()); StringLiteral val = value.getValue(); if (val.isMultiLine()) { val.accept(this); print(")"); } else { print(" " + val + ")"); } } @Override public void visit(Tuple tuple) { print(tuple); } public static void main(String[] args) { PetalFile tree = PetalParser.parse(args); tree.accept(new PrintVisitor(System.out)); } }