All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.uka.ilkd.pp.Printer Maven / Gradle / Ivy

The newest version!
//This file is part of the Java™ Pretty Printer Library (JPPlib)
//Copyright (c) 2009, Martin Giese
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without 
//modification, are permitted provided that the following conditions are met:
// 
// * Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright 
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the distribution.
// * Neither the name of the author nor the names of his contributors 
//   may be used to endorse or promote products derived from this 
//   software without specific prior written permission.
// 
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
//LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
//SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS  SOFTWARE, EVEN IF ADVISED OF 
//THE POSSIBILITY OF SUCH DAMAGE.

package de.uka.ilkd.pp;

import static de.uka.ilkd.pp.IndentationStack.*;
import static de.uka.ilkd.pp.IndentationStack.BreakDecision.*;

/** The intermediate layer of the pretty printing library.  Using the
 * block size information provided by the {@link Layouter} class, this
 * decides where to insert line breaks.  It tries to break as few
 * blocks as possible.  
 *
 * 

Exceptions of type {@code Exc} thrown by the backend will get * passed through to the Layouter. * * @param The type of exceptions that might be thrown by the backend. */ class Printer { /** total line length available */ private final int lineWidth; /** position in current line. */ private int pos; /** total chars written */ private int totalOut = 0; /** Back-end for the pretty-printed output */ private Backend back; /** stack to remember value of pos and * breaking decisions in nested blocks */ private IndentationStack indentStack = new IndentationStack(); /** Create a printer. It will write its output to writer. * Lines have a maximum width of lineWidth. * @param back the Backend to write output to * */ Printer(Backend back) { this.back = back; lineWidth = back.lineWidth(); pos = 0; } /** Write the String s to out * @param s the String to write */ void print(String s) throws Exc { back.print(s); pos += back.measure(s); totalOut += back.measure(s); } /** Begin a block. The parameter followingLength gives * the length of the contents of the block, as determined by Layouter, * or possibly some large number, if the Layouter can determine that * the block will not fit on one line. Depending on the amount of * space left on the line, the layouter decides whether this block * should be broken or not. */ void openBlock(Layouter.BreakConsistency cons, Layouter.IndentationBase indBase, int indent, int followingLength) { if (followingLength > space()) { indentStack.push(indentBase(indBase) + indent, BreakDecision.fromBreakConsistency(cons)); } else { indentStack.push(0, FITS); } } /** end a block */ void closeBlock() { indentStack.pop(); } /** * Write a break. The parameter followingLength is * determined by Layouter and gives the space needed by the * material up to the next corresponding closeBlock() or printBreak(). * It is used to decide whether the current line is continued, * or a new (indented) line is begun. * * @param width the number of spaces printed if the line is not * @param offset the amount added to the indentation level if the line is broken * @param followingLength space required by text up to next break or close * */ void printBreak(int width, int offset, int followingLength) throws Exc { if ( indentStack.topConsistent() || ( indentStack.topInconsistent() && followingLength > space())) { pos = indentStack.topIndentation() + offset; newLine(); } else { writeSpaces(width); pos += width; } } /** Mark this position in the text. This is simply sent * through to the backend. */ void mark(Object o) throws Exc { back.mark(o); } /** Add a number of spaces. The number of spaces * inserted depends on whether the surrounding block is * broken or not. * @param width number of spaces to insert if surrounding block is not broken * @param offest position relative to current indentation level to advance to*/ void indent(int width, int offset) throws Exc { if (indentStack.topFits()) { writeSpaces(width); pos += width; } else { int newMargin = indentStack.topIndentation() + offset; if (newMargin > pos) { writeSpaces(newMargin - pos); pos = newMargin; } } } /** Close the output stream. */ void close() throws Exc { back.close(); } /** Flush the output stream. */ void flush() throws Exc { back.flush(); } /** Return the amount of space currently left on this line. */ int space() { return lineWidth - pos; } /** Return the line width of this Printer. */ int lineWidth() { return lineWidth; } private int indentBase(Layouter.IndentationBase base) { switch(base) { case FROM_POS: return pos; case FROM_IND: if (indentStack.isEmpty()) { return 0; } else { return indentStack.topIndentation(); } default: return 0; } } /** Start a new line and indent according to pos */ private void newLine() throws Exc { back.newLine(); totalOut++; if (pos > 0) { writeSpaces(pos); } } /** how many spaces are in SPACES */ private static final int NR_SPACES = 128; /** a String containing NR_SPACES spaces */ private static final String SPACES; /* initialize SPACES */ static { StringBuilder sb = new StringBuilder(NR_SPACES); for (int i = 0; i < NR_SPACES; i++) { sb.append(' '); } SPACES = sb.toString(); } private void writeSpaces(int n) throws Exc { while (n > NR_SPACES) { back.print(SPACES); n -= NR_SPACES; } back.print(SPACES.substring(0, n)); totalOut += n; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy