Formatting

The format part (right hand side) of a Ppml rule expresses the concrete layout of patterns. Formatting directives may be any of the following:

The type of a box determines how each element- terminal, variable, or other boxes- will be aligned. Ppml provides five types of boxes:

h
: to concatenate elements horizontally.
v
: to concatenate elements vertically. Elements after the first may be indented with respect to the left margin of the first.
v1
: like v, but elements after the first element may be indented with respect to the box surrounding the current box.
hv
: to concatenate elements horizontally until the end of the line is reached. Boxes that don't fit on the current line are folded on to the following line(s) starting at the left margin of the current hv box.
hov
: to concatenate elements horizontally until the end of the line is reached. If the elements don't all fit on the current line, the elements are all concatenated vertically.

The type of a box, also called the global operator, determines the spacing of all elements at the current level. It does not indicate how to format the elements found within nested boxes. In the following example:

[ *x *y [ *s "*" *t] *z]

the results of the instantiation of *x, *y, the inner box and *z are aligned vertically, but *s, ``*'', and *t are aligned horizontally.

We format the plus operator as follows:

[ *x "+" *y]

Ppml provides a device to treat lists -the parentheses operator. We may indicate, between parentheses, how to arrange tokens and elements of a list, and we may even use the ``case'' instruction to select formatting for different operators in the list. Suppose for our operator exp_s we simply want to line up all expressions vertically. We would write:

[ (**exp)]

The next box separates expressions horizontally, unless the list is too long, in which case it separates them vertically:

[ (**exp)]

Note that the following construction:

[ (**exp ";")]

does not separate the elements vertically with a ``;'' at the end of each expression, but arranges everything vertically since the global operator affects all elements in the box. The result is an expression on one line, followed by a semi-colon on the next line, the next expression on the following line, etc. To separate expressions by semi-colons, we modify the box to be:

[ ([ **exps ";"]) *exp]

The box within the parentheses overrides the global operator, so that each expression is paired with a semi-colon horizontally, except the final expression. These pairs are aligned horizontally as long as they all fit, otherwise they are aligned vertically.

Note that this rule corresponds to Exp's concrete syntax definition -expressions are separated by semi-colons. Another concrete syntax definition might have specified that each expression terminates with a semi-colon, in which case we would format each expression with:

[ *exp ";"]

and a list of expressions with:

[ (**exp)]

In this case, the expression rule prints the semi-colon. If we send an expression to a textual editor, both the expression and the semi-colon appear in the editor. Since the concrete syntax definition requires that each expression be terminated by a semi-colon, we may immediately reparse the expression. Using this rule to pretty print Exp expressions would produce visually similar text, but pretty printed expressions would not be reparsable. The basic pretty printer should always format text so that it is reparsable.

In the above examples, we use default values for the different separators. It is often desirable to override these values locally. The Ppml reference manual explains the meaning of each separator's parameters. The operator, for example, has one parameter indicating the number of blank spaces to appear between elements. For example, to specify that elements formatted by the plus rule should be separated by three spaces, we could write:

[ *x "+" *y]

We have everything we need for a simple pretty printer, though we will discuss other techniques and shortcuts presently.


                  



Tutorial