You are on page 1of 11

Functional Pretty Printer Combinators in Scala

Anthony M. Sloane
Programming Languages Research Group
Department of Computing
Macquarie University
Sydney, Australia
http://www.comp.mq.edu.au/~asloane
https://wiki.mq.edu.au/display/plrg

Linear, bounded, functional pretty printing


S. Doaitse Swierstra and Olaf Chitil
Journal of Functional Programming, 19 (1), 1-16, Jan. 2009

Also useful:
Unparsing Expressions With Prefix and Postfix Operators
Norman Ramsey
SoftwarePractice and Experience, 28 (12), 1327-1356, Oct.1998

Basic Combinators
trait Doc {
def <> (e : Doc) : Doc
}
def
def
def
def
def

text (t : String) : Doc


line : Doc
group (d : Doc) : Doc
empty : Doc
nest (d : Doc, j : Indent = defaultIndent) : Doc

def pretty (d : Doc, w : Width = defaultWidth) : Layout

Some Derived Combinators


def char (c : Char) : Doc = ...
def space
def semi

: Doc = char (' ')


: Doc = char (';')

trait Doc {
def <+> (e : Doc) : Doc = this <> space <> e
}
implicit def stringToDoc (s : String) : Doc = text (s)
def value (v : Any) : Doc = string (v.toString)
def enclose (l : Doc, d : Doc, r : Doc) : Doc = l <> d <> r
def parens (d : Doc) : Doc = enclose (lparen, d, rparen)
def ssep (ds : Seq[Doc], sep : Doc) : Doc =
fold (ds, (_ <> sep <> _))
def product (p : Any) : Doc = ...

Simple Imperative Language


trait ImperativeNode
trait Exp extends ImperativeNode
case
case
case
case
case
case

class
class
class
class
class
class

Num
Var
Neg
Add
Sub
Mul

(d
(s
(e
(l
(l
(l

:
:
:
:
:
:

Double) extends Exp


Idn) extends Exp
Exp) extends Exp
Exp, r : Exp) extends Exp
Exp, r : Exp) extends Exp
Exp, r : Exp) extends Exp

trait Stmt extends ImperativeNode


case
case
case
case

class
class
class
class

Null () extends Stmt


Seqn (ss : Seq[Stmt]) extends Stmt
Asgn (v : Var, e : Exp) extends Stmt
While (e : Exp, b : Stmt) extends Stmt

Pretty Printing Imperative Programs


def show (t : ImperativeNode) : Doc =
t match {
case Num (d)
=> value (d)
case Var (s)
=> s
case Neg (e)
=> parens ("-" <> show (e))
case Add (l, r)
=> showbin (l, "+", r)
case Sub (l, r)
=> showbin (l, "-", r)
case Mul (l, r)
=> showbin (l, "*", r)
case Div (l, r)
=> showbin (l, "/", r)
case Null ()
=> semi
case Seqn (ss)
=>
group (braces (nest (line <> ssep (ss map show, line)) <> line))
case Asgn (v, e) => show (v) <+> "=" <+> show (e) <> semi
case While (e, b) =>
"while" <+> parens (show (e)) <> group (nest (line <> show (b)))
}
def showbin (l : ImperativeNode, op : String, r : ImperativeNode) : Doc =
parens (show (l) <+> op <+> show (r))

Demo...

Implementation (1)

pretty
TreeCont

Indent
Width

Doc

Tree
Cont

TreeCont

Pos Dq

Remaining

Tree
Cont

Out

Out

""

0 emptyDq

0
Layout
w

Doc

Tree
Cont

Out

Implementation (2)
nest (d, j)

empty

l <> r

Code...

Downloads

This Scala implementation is included in the latest release of the


Kiama language processing library:
http://kiama.googlecode.com

You might also like