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

com.io7m.jsx.prettyprint.JSXPrettyPrinterCodeStyle Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/*
 * Copyright © 2016 Mark Raynsford  https://www.io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jsx.prettyprint;

import com.io7m.jsx.SExpressionType;
import com.io7m.jsx.SExpressionType.SListType;
import com.io7m.jsx.SExpressionType.SQuotedString;
import com.io7m.jsx.SExpressionType.SSymbol;
import de.uka.ilkd.pp.Layouter;
import de.uka.ilkd.pp.WriterBackend;

import java.io.IOException;
import java.io.Writer;
import java.util.Objects;

/**
 * A pretty printer tailored to printing expressions that represent Lisp-like
 * code.
 */

public final class JSXPrettyPrinterCodeStyle implements JSXPrettyPrinterType
{
  private final WriterBackend backend;
  private final PrinterMatcher matcher;

  private JSXPrettyPrinterCodeStyle(
    final Writer in_out,
    final int width,
    final int indent)
  {
    final Writer out = Objects.requireNonNull(in_out, "Writer");
    this.backend = new WriterBackend(out, width);
    final Layouter layout = new Layouter<>(this.backend, indent);
    this.matcher = new PrinterMatcher(layout, indent);
  }

  /**
   * Create a new pretty printer.
   *
   * @param in_out    The output writer
   * @param in_width  The maximum output width (note that unbreakable lines may
   *                  exceed this width)
   * @param in_indent The indent for nested expressions
   *
   * @return A new printer
   */

  public static JSXPrettyPrinterType newPrinterWithWidthIndent(
    final Writer in_out,
    final int in_width,
    final int in_indent)
  {
    return new JSXPrettyPrinterCodeStyle(in_out, in_width, in_indent);
  }

  @Override
  public void print(final SExpressionType e)
    throws IOException
  {
    this.matcher.match(e);
  }

  @Override
  public void close()
    throws IOException
  {
    this.backend.flush();
  }

  private static final class PrinterMatcher
  {
    private final int indent;
    private final Layouter layout;

    PrinterMatcher(
      final Layouter in_layout,
      final int in_indent)
    {
      this.layout = Objects.requireNonNull(in_layout, "Layout");
      this.indent = in_indent;
    }

    public Void match(
      final SExpressionType e)
      throws IOException
    {
      if (e instanceof SQuotedString quotedString) {
        return this.quotedString(quotedString);
      } else if (e instanceof SSymbol symbol) {
        return this.symbol(symbol);
      } else if (e instanceof SListType list) {
        return this.list(list);
      } else {
        throw new IllegalStateException();
      }
    }

    public Void list(final SListType e)
      throws IOException
    {
      final Layouter x = this.layout;

      x.begin(
        Layouter.BreakConsistency.CONSISTENT,
        Layouter.IndentationBase.FROM_POS,
        0);

      if (e.isSquare()) {
        x.print("[");
      } else {
        x.print("(");
      }

      final int size = e.size();
      if (size > 0) {
        for (int index = 0; index < size; ++index) {
          final SExpressionType current = e.get(index);
          this.match(current);
          if (index + 1 < size) {
            x.brk(1, this.indent);
          }
        }
      }

      if (e.isSquare()) {
        x.print("]");
      } else {
        x.print(")");
      }

      x.end();
      return null;
    }

    public Void quotedString(final SQuotedString e)
      throws IOException
    {
      this.layout.print(String.format("\"%s\"", e.text()));
      return null;
    }

    public Void symbol(final SSymbol e)
      throws IOException
    {
      this.layout.print(e.text());
      return null;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy