Pretty Print Table

XT -- A Bundle of Program Transformation Tools

Introduction

Pretty-print tables are used to specify how language constructs have to be pretty-printed and are used in combination with GenericPrettyPrinter front-ends. Pretty-print tables use Box as language to specify formatting of language constructs. A pretty-print table contains mappings from constructor names of SDF language productions to Box expressions.

For example, for the SDF production

  f ( A ) -> B {cons("f")}

A pretty-print entry looks like:

  f -- H [ "f" "(" _1 ")" ]

Pretty-print tables are ordered such that pretty-print rules occuring first take preceedence over overlapping pretty-print rules defined later. The syntax of pretty-print tables is available in the online Sdf.Trash.GrammarBase.

Rule Selectors

To be able to specify formattings for all nested constructs that are allowed in SDF productions, so called selectors are used in pretty-print tables to refer to specific parts of an SDF production and to define a formatting for them. For example, the SDF prodcution

  f ( A? ) -> B {cons("f")}

contains a nested symbol A?. To specify a formatting for this production, two pretty-print entries can be used:

  f      -- H [ "f" "(" _1 ")" ]
  f.1:opt   -- H [_1]

A selector consists of a constructor name followed by a list of number+type tuples. A number selects a particular subtree of an SDF construct, the type denotes the type of the selected construct (sequence, optional, separator list etc.). This rather verbose selector mechanism allows unambiguous selection of subtrees of SDF productions. Its verbosity (by specifying both the number of a subtree and its type), makes pretty-print tables easier to understand and, more importantly, it enables pretty-printing of AST's, because with type information, a concrete term can be correctly recontructed from an AST. Pretty-print tables can thus be used for both formatting of parse-trees and AST's.

Below we summarize which selector types are available:

opt
For SDF optionals (S?).

iter
For non-empty SDF lists (S+).

iter-star
For possible empty SDF lists (S*).

iter-sep
For SDF separator lists ( {S_1 S_2}+). Observe that the symbol S_1 and the separator S_2 are ordinary subtrees of the iter-sep construct which can be refered to as first and second subtree, respectively.

iter-star-sep
For SDF separator lists ( {S_1 S_2}*). Its symbol and separator can be refered to as first and second sub tree.

alt
For SDF alternatives (A_1 | A_2 |A_3). According to the SDF syntax, alternatives are binary operators. The pretty-printer flattens all subsequent alternatives. Pretty-print rules can be specified for each alternative individually by specifying the number of each alternative. To be able to format literals in alternative, a special formatting rule can be defined for the construct (See the examples below).

seq
For SDF sequences ( (S_1 S_2 S_3) ).

Examples

Below we list a simple SDF module with productions containing all above constructs:

 module Symbols
 exports
 context-free syntax 
   A?          -> S {cons("ex1")}   
   A+          -> S {cons("ex2")}
   A*          -> S {cons("ex3")}
   {S1 S2}+       -> S {cons("ex4")}   
   {S1 S2}*       -> S {cons("ex5")}   
   "one" | "two" | S?    -> S {cons("ex6")}   
   ("one"  "two" S? )    -> S {cons("ex7")}

The following pretty-print table shows which pretty-print rules can be defined for this syntax:

 [
   ex1          -- _1,
   ex1.1:opt       -- _1,
   ex2         -- _1,
   ex2.1:iter      -- _1,
   ex3          -- _1,
   ex3.1:iter-star    -- _1,
   ex4          -- _1,
   ex4.1:iter-sep       -- _1 _2,
   ex5          -- _1,
   ex5.1:iter-star-sep    -- _1 _2,
   ex6          -- _1,
   ex6.1:alt       -- KW["one"] KW["two"] _1,
   ex6.1:alt.1:opt       -- _1,
   ex7          -- _1,
   ex7.1:seq       -- KW["one"] KW["two"] _1,
   ex7.1:seq.1:opt    -- _1
 ]

The pretty-print rule 'ex6.1:alt' is a special case. It contains three Box expressions, one for each alternative. It is used to specify a formatting for the non-nested literals "one" and "two". During pretty-printing one of the three BOX expressions is selected, depending on alternative contained the term to format.

Pretty-Print Table Generation

Pretty-print tables can be generated from SDF syntax definitions (see ppgen?). Generated pretty-print rules can easiliy be customized by overruling them in additional pretty-print tables. The tool pptable-diff notifies inconsistensies in pretty-print tables after the syntax definition has changed and can be used to brin inconsistent table up-to-date.

See Also