%
% $Id: chap2.tex,v 1.8 1995/04/20 13:08:27 gaertner Exp gaertner $
%
% $Log: chap2.tex,v $
% Revision 1.8  1995/04/20  13:08:27  gaertner
% Corrections proposed by JS
%
% Revision 1.7  1995/02/24  09:26:10  gaertner
% Final touches.
%
% Revision 1.6  1995/02/23  12:19:37  gaertner
% Deleted noisy index entries.
%
% Revision 1.5  1995/02/23  10:59:47  gaertner
% Fine tuned whole chapter (including index).
%
% Revision 1.4  1994/10/31  18:33:54  gaertner
% Finished revision of this chapter. Need to do some fine
% tuning later.
%
% Revision 1.3  1994/10/27  18:33:21  gaertner
% Revised text up to section about the `preBISON' file. Added
% a section about advaced topics that still has to be filled.
% Contents will be the redefinition of scanner and parser
% interfaces and inclusion of additional C code at the end.
%
% Revision 1.2  1994/10/25  16:48:42  gaertner
% Went over beginning sections of this chapter. Revised
% first figure.
%
%


\chapter{\label{two}Using Pretzel}




Pretzel is a program that generates a prettyprinter module from a
formal description of the way a certain language should be
prettyprinted.  (NB: Pretzel produces {\em modules}, not programs!)
This chapter is the user's manual for \pretzel.  It first gives an
overview of how \pretzel\ works and how the generated prettyprinter can
be used. Secondly it takes a close look at the formats of the two
input files to \pretzel, the formatted token and the formatted grammar
files. Thirdly, this chapter states how the program is invoked and how
the input is turned into the prettyprinter. Finally there is a
complete example for a prettyprinter for \PASCAL\ that was generated
by \pretzel.

\index{User's manual}\index{pascal@\PASCAL}


\section{The Concept of Pretzel}

The concept of \pretzel\ is visualized in figure \ref{concept}.  From
a formal formatting description of a programming language $P$,
\pretzel\ generates a prettyprinting function that can be used to
prettyprint source code in $P$. To get the actual prettyprinting
program, you only have to supply a main program (or use the one that
comes with \pretzel). If the way of prettyprinting needs to be
changed, the user only needs to change formal parts in the input and
use \pretzel\ again to get an enhanced prettyprinter.

\index{pretzel@\pretzel!concept}
\index{P@$P$}


\begin{figure}
\begin{center}

\setlength{\unitlength}{0.012500in}%

\begin{picture}(203,87)(8,744)
\put( 90,789){\makebox(0,0)[b]{pretzel}}
\thinlines
\put( 54,744){\framebox(72,18){}}
\put( 87,777){\vector( 0,-1){  9}}
\thicklines
\put( 30,753){\vector( 1, 0){ 18}}
\put(129,753){\vector( 1, 0){ 24}}
\thinlines
\put( 66,783){\framebox(45,18){}}
\put( 87,819){\vector( 0,-1){ 12}}
\put( 90,822){\makebox(0,0)[b]{formal description}}
\put( 90,750){\makebox(0,0)[b]{prettyprinter}}
\put( 18,750){\makebox(0,0)[b]{Text}}
\put(183,759){\makebox(0,0)[b]{prettyprinted}}
\put(177,744){\makebox(0,0)[b]{text}}
\end{picture}

\end{center}

\caption{The concept of \pretzel.}
\label{concept}

\end{figure}


Figure \ref{detailed-concept} on page \pageref{detailed-concept} shows
the generating process in slightly more detail. The figure shows that
the program \pretzel\ doesn't generate a prettyprinter immediately;
what it does is to produce code that can be turned into a \CPP\
prettyprinting function with the help of two tools:
 %
\index{c++@\CPP}
 %
\begin{description}

\item[flex] A POSIX.2 compliant lexical analyser generator.

\item[Bison] A POSIX.2 compliant parser generator. The version
used with \pretzel\ has to produce \CPP\ compliant source.

\end{description}

\index{flex}\index{Bison}\index{POSIX}

\noindent Users that are already familiar with the basics of both
tools will find it easier to read the following text because the way
of specifying input to \pretzel\ is quite close to the ways used by
them. However, this text aims at people who don't have such knowledge
and will explain everything that is necessary.

Also visible from this figure is that \pretzel\ creates two things:

\begin{itemize}

\item A prettyprinting scanner and

\item a prettyprinting parser (the actual prettyprinter).

\end{itemize}

\index{Prettprinting scanner}\index{Prettyprinting parser}

The prettyprinting parser is the actual prettyprinter function that you
normally want to get when using \pretzel. The prettyprinting scanner is
used by the parser and takes care of the token formatting. Both
parts are separate modules with a well defined interface and can be
used individually. Hence, you can write your own scanner or parser if
you really need features that the ones produced by \pretzel\ don't have.
(For a description of the interface to both, see section
\ref{pp-interface} or the specifications of the two generator
functions for a complete reference.)





\subsection{The Input Files}

The word ``pretty'' is very subjective and so programming language
source code can be printed in a ``pretty'' kind of fashion in almost
infinitely many ways, according to the taste and preferences of the
user. If the task of prettyprinting is handed over to the computer,
the user must specify in detail all of his wishes towards the
appearance of the output of the prettyprinter.

To generate a prettyprinter, \pretzel\ needs two descriptions that it
expects to find in two different files:

\begin{description}

\item[A formatted token file.] This file should contain all information
  concerning the individual formatting of tokens (i.e.~identifiers,
  reserved words, etc.).

\item[A formatted grammar file.] This file should contain a prettyprinting
  grammar, i.e.~a context free grammar enhanced with formatting commands.
  This information is necessary to handle the more global aspects of
  prettyprinting that need information about the language context
  (i.e.~indentation, line breaks, etc.).

\end{description}

\index{Formatted token file}\index{Formatted grammar file}

\noindent The name of the first file might be a little misleading, since
it doesn't contain formatted tokens. Instead it tells you what you will
get from the definitions therein. A name like ``token formatting file''
might have been a little better, but the similarity in names between the
two input files sounded good and seemed to outplay this small inconsistency.

The special formats of these two files are described later in section
\ref{file-formats}. Let's first look at what the generated scanner
and parser functions look like.


\begin{figure}[htb]
  \begin{center}
    \leavevmode
    \input{../figures/detailed-concept.latex}
  \end{center}
  \caption{The current process of generating a prettyprinter with \pretzel.}
  \label{detailed-concept}
\end{figure}




\subsection{The Generated Prettyprinting Functions}
\label{pp-interface}

So there are two inputs to \pretzel. And if these inputs are okay and
the program runs without error, you will obtain an output from which a
\CPP\ prettyprinting function can be made. The output of \pretzel\ are
two files. The first file is a valid Bison file from which the
actual prettyprinting parser can be obtained. The second file
(generated from the formatted token file) can be processed with the
scanner generator to form the prettyprinting scanner used by the
parser.

\index{Bison}\index{c++@\CPP}

The generated Bison file contains all definitions for the actual
prettyprinting function. It's default interface is:

\begin{outp}
\res{void} \id{pparse} (\id{istream}$\ast$, \id{ostream}$\ast$);
\end{outp}

This is in the flesh the desired prettyprinter. The input (source code
text) enters the prettyprinter through an input stream (i.e.~a \CPP\
\id{istream} object) and leaves the prettyprinter through an output
stream (i.e.~a \CPP\ \id{ostream} object). This output isn't actually
prettyprinted yet. By default the output is delivered in a format
suitable for \TeX\ to typeset it. It can be changed however to suit
any other typesetter. (The output format is very much part of the
implementation of the \id{Output} class. See into the appendix
for details.)

The prettyprinting function depends on a separate function that cuts
the input file into small bits (tokens) and does the local
formatting. This function is provided in the scanner generator source
produced from the formatted token file. It's default interface
consists of two functions:

\begin{outp}
\res{void} \id{pscan\_init} (\id{istream}$\ast$);\myforce
\res{int} \id{pscan} (\id{Attribute}$\ast\ast$);
\end{outp}

The first function serves as an initializer and tells the scanner
where it should take its input from. The second function is
the actual scanner. It scans the input and returns token codes
as integer numbers. These codes have to be the same as the ones
used by the parser (look at section \ref{fg-file} for details).
The formatted look of this token is handed back as a call-by-reference
argument of type \id{Attribute}.

\index{attribute class@\id{Attribute} class}
\index{Interface of the scanner}

Please note that the interface of the prettyprinting scanner is
exactly how the parser above expects it to be. If you are planning to
create a normal prettyprinter you won't have to bother about the
interface of the scanner, because it works together fine with the
parser. If you really need to know more details or want to change the
default interface in any way, look into section \ref{hacks} for a
description of some of the more specialized topics.

To use the prettyprinting functions in a \CPP\ program, header files
are needed that declare the interface.  From the information above it
is possible for you to write your own header files for the generated
scanner or parser. But \pretzel\ spares you from this job, however, as
it offers two template header files that you can copy and edit to suit
your own purposes. They provide the default interface of both
functions. Look into the {\tt README} file for an exact description of
their location in the \pretzel\ distribution.








\section{The Format of the Input Files}
\label{file-formats}

\index{File formats}

Now we turn to a vital thing for the user of \pretzel: The format of
the \pretzel\ input files. Here the user has to put a formal description
of the underlying programming language and (with the help of format
commands) state how its text should be formatted.

We have seen that \pretzel\ takes two input files: The formatted token
file and the formatted grammar file. We suggest to use the suffix
`{\tt .ft}' for a formatted token file and `{\tt .fg}' for a formatted
grammar file.

\index{ft@\t{.ft} suffix}\index{fg@\t{.fg} suffix}
\index{Filename conventions}\index{Conventions}



\subsection{The Formatted Token File}

\index{Formatted token file}

The formatted token file contains a list of token definitions with their
corresponding ``prettyprinted'' form. The prettyprinted form of a
token will be called an {\em attribute} or a {\em translation}.

The general outline of the formatted token file is
 %
\begin{outp}
\id{declarations}

\t{\%\%}

\id{token definitions}
\end{outp}
 %
Normally, the {\em declarations} part is empty. You can put a general
description of the file here (as a \C\ comment) and redefinitions of
the default interface go here as well (see section \ref{hacks} for
more).

The {\em token definitions} section of the formatted token file contains a
series of token definitions of the form:
 %
\begin{outp}
\id{pattern}\qquad \id{token}\qquad \{\id{attribute}\}
\end{outp}
 %
The {\em pattern} must be a valid regular expression (in terms of {\tt
  flex}) and must be unindented. The {\em token} specifies the
symbolic name of the token for the pattern and begins at the first
non-whitespace character after the pattern. The token name must be a
legal name for an identifier in \PASCAL\ notation and {\em must be all
  in upper case}. (Underlines are allowed but not at the beginning of
a word.)

\index{pascal@\PASCAL}

The {\em attribute} for this token, that is it's prettyprinted form,
consists of all text between the two curling brackets `\{' and
`\}'. Attributes can be either simple strings (surrounded by double
quotes) or format commands (like \fmt{force}, \fmt{indent}) or a
combination of both joined together by the `\t{+}' sign. Attribute
definitions can cover several lines and the starting `\{' needn't
stand on the same line as the token definition; however subsequent
lines must be indented with at least one blank or one tab.

If you define strings as part of an attribute definition, you have
to specify them in a \C\ kind of fashion, i.e.~you can insert
newlines and tabs with `\verb+\n+' and `\verb+\t+'. But if you want
to insert a backslash into a string, you mustn't forget to put two
backslashes (`\verb+\\+') into the input file. This is especially
noteworthy if you are using \TeX\ as typesetter, because \TeX\
uses a backslash as a prefix for typesetting commands.

If the definition of the attribute is omitted \pretzel\ creates an
attribute for this pattern by default. The default attribute
consists of the string containing the text matched by the
corresponding pattern.

The user himself may also refer to the matched text by using the
sequence `\t{**}'. Thus
 %
\begin{verbatim}
  "foo"       BAR
  "foo"       BAR     { ** }
  "foo"       BAR     { "foo" }
\end{verbatim}
 %
all have the same meaning.

You can use a `\t{|}' sign as a token name; this signals that the
current regular expression has the same token name (and also the same
attribute) as the token specified in the following line (empty lines
are ignored). An attribute definition behind a `\t{|}' is illegal.
However you may specify regular expressions with neither a token name
nor an attribute to give a default rule or to eat up whitespace.

The following examples are all legal token definitions (and please
note the dot in the very last line):

\begin{verbatim}
  [0-9]           DIGIT

  "{"             OPEN           { "\\{" + indent + force }

  [a-z][a-z0-9]*  ID             { "{\\it " + ** + "}" }

  "function"      |
  "procedure"     PROC_INTRO     { big_force + ** }

  [\t\ \n]        |
  .
\end{verbatim}


The declarations and the token definitions must be separated by a
line containing only the two characters \t{\%\%}. So the shortest
possible formatted token file is
 %
\begin{verbatim}
   %%
\end{verbatim}
 %
but this doesn't seem of any use, does it?




\subsection{The Formatted Grammar File}
\label{fg-file}

\index{Formatted grammar file}

In the formatted grammar file the user encodes the general
prettyprinting grammar for the programming language. This is done by
specifying a context free grammar of the language and by adding
information about the creation of new attributes in every rule.

\index{Context free grammar}

The formatted grammar file is the second and last input to the \pretzel\
program. Its general outline looks like this:

\begin{outp}
\id{token declarations}

\t{\%\%}

\id{grammar rules}
\end{outp}

The {\em token declarations} section may be empty and the separator
between the two parts of the file (\t{\%\%}) must appear
unindented on a single line by itself. Before we look at these
declarations, let's have a look at the grammar rules.

The {\em grammar rules} section contains the collection of rules of
the context free grammar that can be accompanied by an attribute
definition.  A rule is specified by stating the resulting token, a
colon and then the series of tokens which will be reduced by this
rule. The rule is ended by a semicolon. A block definition in \PASCAL\
for example might look like this:
 %
\begin{verbatim}
  block : BEGIN stmt_list END
  ;
\end{verbatim}

Following the token list on the right side of the colon can be an
attribute definition; this definition states, how the translation of
the produced symbol is obtained from the tokens on the right side of
the rule.

An attribute definition is bracketed amidst curling brackets `\{'
and `\}' and can again consist of strings (in double quotes) and
format commands or both joined together with `\t{+}'. But here you
can also refer to the attributes of the tokens on the right side
of the rule. This is done in a slightly awkward notation with a number
that is preceded with a `\t{\$}' dollar sign. The numbers refer to
the order of appearance of the symbols on the right side of the
rule. So `\t{\$1}' refers to the first token of the rule,
`\t{\$2}' to the second, \dots

Again attribute definitions are allowed to span several lines and
strings must be specified in \C\ manner.

\index{c@\C}

For example, here again is the possible definition of a block in
\PASCAL, now with an example attribute definition:
 %
\begin{verbatim}
  block : BEGIN stmt_list END   { $1 + $2 + force + $3 }
  ;
\end{verbatim}

\index{pascal@\PASCAL}

The attribute of a \t{block} will therefore consist of the
attributes of the \t{BEGIN} and \t{stmt\_list} tokens, joined
together with a \fmt{force} command and the translation of the
\t{END} token.

The attribute definition may be omitted. If this is so, \pretzel
will by default form the attribute of the produced symbol from the
simple concatenation of the attributes on the right side of the
rule. For instance
 %
\begin{verbatim}
  stmt : block SEMI
  ;
\end{verbatim}
 %
means the same as:
 %
\begin{verbatim}
  stmt : block SEMI       { $1 + $2 }
  ;
\end{verbatim}

Of course you may also have empty right sides of a rule (to produce
things out of nothing) or simply concatenate two or more rules
resulting in the same symbol with a `\t{|}'. So the following are
legal rules:
 %
\begin{verbatim}
  stmt_list   :                      { force }
              | stmt_list stmt SEMI  { $1 + $2 + $3 + force }
  ;
\end{verbatim}


To end this subsection, we have to return to the {\em token
declarations} section of the formatted grammar file. Here we have to insert
a special line for every terminal token that appears in the grammar
rules. These definitions are of the form `\t{\%token} \id{tokenname}'.
This part of the formatted grammar file is owed to Bison and should
be removed in subsequent versions.




\subsection{Comments and Code}

\index{Comments!in \pretzel\ input files}

There is a very simple way of putting comments into the formatted
token and formatted grammar files. This is done in a \CPP\ kind of
manner by preceding the comment with a double slash (`\t{//}'). All
characters between this sign and the end of the line are ignored by
pretzel.

\index{c++@\CPP}

In both files you can put additional \CPP\ code before and after the
definitions/grammar sections.  If you want to insert code at the end
of your file, you have to put a second `\t{\%\%}' on a line by itself
and put the code behind it. \C/\CPP\ Code before the definitions/rules
section has to be tied in with a `\%\{', `\%\}' pair. Inserting extra
code will however only become interesting if these functions could be
accessed from inside the attribute definitions of the grammar. This
might be possible in a later version of \pretzel.




\section{Making a Prettyprinter with Pretzel}

So if you have specified the two necessary files that describe a
prettyprinter for your favourite programming language called, say $P$
now, you will have a formatted token file called \t{p.ft} and a
formatted grammar file called \t{p.fg}. To get your prettyprinter from
these two files you have to successively invoke \pretzel, flex, Bison
and your \CPP\ compiler. It is very convenient to use the
\t{make} tool to support you with this task. There is a typical
\t{Makefile} for such cases included in the \pretzel\ distribution.
You can use it as a starting point for your own files.

\index{makefile@\t{Makefile}}
\index{flex}\index{Bison}\index{c++@\CPP}




\subsection{Invoking Pretzel}

The first step would be to produce the flex and Bison files using
\pretzel. \pretzel\ is invoked by typing
 %
\begin{verbatim}
  pretzel
\end{verbatim}
 %
at the command line. The full usage of \pretzel\ can be
obtained using the \t{-h} option. It is:
 %
\begin{verbatim}
  pretzel [-qtgdh] [-o outfile] (prefix | file1 file2)
\end{verbatim}
 %
Here's an explanation of the options:
 %
\begin{description}

\item[-q] Run quietly (no screen output).

\item[-t] Process formatted token file only.

\item[-g] Process formatted grammar file only.

\item[-d] Run in debug mode (i.e.~print out debugging information
on the screen while running).

\item[-h] Show full usage.

\item[-o outfile] Names of the produced output files begin with ``outfile''.

\end{description}
  %
The options \t{-t} and \t{-g} are mutually exclusive, i.e.~you
can't choose both at the same time.

\index{pretzel@\pretzel!options}

The command line parameters have different meanings depending on
whether one ore two names are given. If there is only one parameter,
it specifies the prefix of both formatted token and formatted grammar
files. The suffixes `{\tt .ft}' and `{\tt .fg}' are assumed. But if
there are two parameters at the command line, \pretzel\ will take the
first as full name of the formatted token file and the second as full
name of the formatted grammar file. In this case, the output files
will get a default name. The output files will have endings `{\tt .l}'
(token file) and `{\tt .y}' (grammar file).

\index{ft@\t{.ft} suffix}
\index{fg@\t{.fg} suffix}
\index{l@\t{.l} suffix}
\index{y@\t{.y} suffix}



\subsection{An Example Pretzel Session}

So let's return to our initial example with our programming
language $P$ for which we want to build a prettyprinter. To get
both valid flex and Bison files we invoke \pretzel\ with:
 %
\begin{verbatim}
  pretzel -o printp p
\end{verbatim}
 %
This will result in two new files, namely \t{printp.l} and
\t{printp.y}. (The \t{-o} option defines the prefix of the
output files.) The \t{.l}-file is the flex file and the
\t{.y}-file is the Bison input. So now try
 %
\index{pretzel@\pretzel!options}
\index{options of@Options of \pretzel}
\index{l file@\t{.l} file}
\index{y file@\t{.y} file}
\index{flex input}
\index{Bison input}
 %
\begin{verbatim}
  flex printp.l
  bison -d printp.y
\end{verbatim}
 %
to create \CPP\ code for your prettyprinter. After renaming the output
files of flex and Bison to, say, \t{myscan.c} (flex) and \t{myparse.c}
(Bison) you have to compile both. After compilation you will get
object files that, together with the default headers, form the
prettyprinter module. Other programs, that want to use the prettyprinter, only
have to include the header file and be linked with the resulting object
files. Figure \ref{simple-main} shows a minimal main program that reads
from the standard input and outputs the prettyprinted code to the
standard output.

\begin{figure}[htbp]
  \begin{center}
    \leavevmode
\begin{verbatim}
/*
 * a minimal main program to test a pretzel prettyprinter
 */

#include <iostream>
#include "pparse.h"       // include the header of the prettyprinter

int main () {
    pparse(&cin,&cout);   // call the prettyprinter function
    return(0);
}
\end{verbatim}
    \caption{A minimal main program that uses a \pretzel\ prettyprinting function.}
    \label{simple-main}
  \end{center}
\end{figure}

The \t{-d} option of Bison produces a so called `token
header' file needed by the scanner (see figure \ref{detailed-concept}
on page \pageref{detailed-concept}). It contains information about all
of the non-terminal tokens that the parser knows of. The scanner
expects to find it under the name \t{ptokdefs.h}, so you should rename
this file to meet the scanner's expectations.


\index{myscan@\t{myscan.c}}
\index{myparse@\t{myparse.c}}
\index{ptokdefs@\t{ptokdefs.h}}
\index{Prettyprinter!token header file}
\index{Token header file}
\index{Bison!d option@\t{-d} option}
\index{d option@\t{-d} option of Bison}
\index{Common token header file}
\index{Prettyprinter!header file}
\index{Header file!of \pretzel\ prettyprinter}





\subsection{Debugging the Prettyprinting Grammar}

\index{Debugging the prettyprinting grammar}

According to the prettyprinting grammar you specify, the generated
prettyprinting function will parse the input text and try to
prettyprint it. However, it sometimes may be impossible for the
parser to parse the input according to the supplied rules. In such
a case, the prettyprinted output may look a bit strange (a lot of
stuff will be missing), but the prettyprinter will never stop or
even issue an error.

To fine-tune your grammar and look for the place it couldn't cope
with, you can switch on a debugging feature that offers you are
large amount of tracing information. You can switch it on by
setting the external integer \t{yydebug} to a nonzero value. As
soon as this is done and the parsing starts, you will see the
standard Bison tracing reports. In addition to this, the attribute
of every token read is displayed directly after the token name
inside brackets when a new token is read. However, depending on the
complexity of your grammar and the length of the input, parsing
can take very long if you have the tracing feature switched on. So
you should debug your prettyprinting grammar with small examples.

\index{yydebug@\t{yydebug}}



\subsection{Advanced Topics}
\label{hacks}

This section finally tells you some ways to fine tune your prettyprinter.

\pretzel\ allows you to rename the prettprinting functions. This is done
via \C\ preprocessor makros. Here's a list of makros with which you
can influence the interfaces of prettyprinting scanner and parser.
We'll see how to redefine them in a moment.

\begin{description}

\item[{\tt PPARSE\_NAME}] This makro is the name of the prettyprinting
parser (`{\it pparse}' by default).

\item[{\tt PSCAN\_NAME}] This makro holds the name of the
prettyprinting scanner (`{\it pscan}' by default).

\item[{\tt PSCAN\_NAME\_INIT}] This is the name of the initialiser
function of the scanner (`{\it pscan\_init}' by default).

\item[{\tt PTOKDEFS\_NAME}] This is the name of the common token
header file that defines the token codes of the terminal tokens
returned by the prettyprinting scanner (`{\tt ptokdefs.h}'' by
default).

\end{description}

\index{pparse name@\t{PPARSE\_NAME}}
\index{pscan name@\t{PSCAN\_NAME}}
\index{pscan name init@\t{PSCAN\_NAME\_INIT}}
\index{ptokdefs name@\t{PTOKDEFS\_NAME}}

The names of these functions will be defined if the user doesn't have
his own definition.
For example, if you want to change the name of the prettyprinting
scanner to `{\it foo}', you have to put lines like this into
the declarations section of your formatted token file:
 %
\begin{verbatim}
%{
#define PSCAN_NAME foo
%}
\end{verbatim}
 %
Note that you can only change the names of the functions, not other
parts of their interface. (The `\verb+%{+' and `\verb+%}+' are necessary
because the line in between is \C\ code.)

The prettyprinting parser implicitly expects to have a scanner
available for parsing under the default name. So if you are using a
prettyprinting scanner with a different name you have to redefine the
same makro again in the formatted grammar file.



\section{Example (a Grammar for \PASCAL)}

To end this chapter I will try to give a small impression about the
looks of a formatted token and a formatted grammar file by giving a
small example. The following inputs are excerpts of a prettyprinting
grammar for something like \PASCAL. It was basically derived from
Knuth's context sensitive grammar in his original \WEAVE\ program, but
suits my own formatting preferences. The typesetter used in this
example is \TeX\ using the macro definitions from Knuth's \t{cwebmac}
macro package for \CWEB. Basicly, you could use any typesetter that
has in-text procedural markup. The only thing you have to do is to
write a macro package with a special tag for every format command and
have the \pretzel\ prettyprinter output these special tag names
instead of the current control sequences (\verb+\1+ \dots\ \verb+\7+).
Using the {\tt cwebmac} package spared me from having to write my own
set of commands and works fine for demonstration purposes.  (See
chapter \ref{five} on the problems of changing output formats.)


Note that if you want to use the following code for playing around,
you have to tell flex to create a case-insensitive scanner since
reserved words are only noticed in lowercase.

\index{pascal@\PASCAL}\index{weave@\WEAVE}\index{Example grammar}
\index{Prettyprinter!example}\index{Knuth, Donald E.}
\index{Context sensitive grammar}\index{tex@\TeX}\index{cwebmac@\t{cwebmac}}
\index{cweb@\CWEB}

The sequence `\verb+[...]+' denotes that parts are left out from the
original file.


\subsection{The Formatted Token File}

\begin{verbatim}
/* pretzel formatted tokens for simple PASCAL */

%%

"<>"       MATH     { "$\\neqI$" }         // not equal sign
"<="       MATH     { "$\\leq$" }          // less or equal
">="       MATH     { "$\\geq$" }          // greater or equal
":="       MATH                            // assignment
'([^']|'')*'    SIMP                       // strings
"("        OPEN
")"        CLOSE

"["        OPEN
"]"        CLOSE
"*"        MATH     { "$\\ast$" }
","        MATH     { ** + opt9 }
".."       MATH
"."        SIMP
":"        COLON
";"        SEMI
"="        MATH
"+"        MATH
"-"        MATH
"<"        MATH     { "$<$" }
">"        MATH     { "$>$" }
"/"        MATH
                 // this to allow underscores in identifiers:
"_"[a-zA-Z0-9]*    ID_TYPE    {"\\" + ** }

[0-9]+             SIMP
[0-9]*"."[0-9]+    SIMP

and        MATH     {"\\AND "}
array      ALPHA    {"\\&{array}"}
begin      BEG      {force + "\n" + "\\&{begin}" }
boolean    SIMP     {"\\&{boolean}"}
case       CASE     {force + "\\&{case}" + cancel }
const      INTRO    {force + backup + "\\&{const}"}
div        MATH     {" \\&{div} "}
do         OMEGA    {"\\&{do}"}
downto     MATH     {"\\&{downto}"}
else       ELSE     {"\\&{else}" }
end        END      {"\\&{end}" }
for        ALPHA    {"\\&{for}" }
function   PROC     {big_force + backup + "\\&{function} " }
if         ALPHA    {"\\&{if}" }
integer    SIMP     {"\\&{integer}"}
mod        MATH     {"\\&{mod}"}
not        MATH     {"\\neg "}
of         OMEGA    {"\\&{of} " + cancel }
or         MATH     {"\\V "}
procedure  PROC     {big_force + backup + "\\&{procedure} " }
program    PROC     {big_force + backup + "\\&{program} "}
readln     SIMP     {"\\&{readln}"}
real       SIMP     {"\\&{real}"}
record     RECORD   {"\\&{record}"}
repeat     BEG      {force + "\\&{repeat}" }
then       OMEGA    {"\\&{then}" }
to         MATH     {" \\&{to} "}
type       INTRO    {force + backup + "\\&{type}" }
until      UNTIL    {force + "\\&{until}" }
var        INTRO    {force + backup + "\\&{var} "  }
while      ALPHA    {force + "\\&{while}" }
with       ALPHA    {force + "\\&{with}"}
write      SIMP     {"\\&{write}"}
writeln    SIMP     {"\\&{writeln}"}


"{"[^}]*"}"    COMMENT    { "\\C{" + ** + "}" }

[a-zA-Z][a-zA-Z0-9]*    ID_TYPE    // identifiers

[\t\ \n]          // eat up whitespace

.                 // eat up other non matching characters

\end{verbatim}

\subsection{The Formatted Grammar File}

\begin{verbatim}
/* pretzel formatted grammar for simple PASCAL. */

%token SEMI
%token BEG
%token END
%token MATH           // token should only be used in math mode
%token SIMP           // other simple tokens
%token OPEN
%token CLOSE
%token ALPHA
%token OMEGA
%token UNTIL
%token INTRO
%token PROC
%token COLON
%token ELSE
%token COMMENT
%token ID_TYPE
%token RECORD
%token CASE

%%

stmt_list    : stmt                // collect everything on a
             | stmt_list  stmt     // list of `statements'
;
    // what can statements be?
stmt         : COMMENT             {cancel + $1}
             | proc                // procedure heading
             | SEMI                // empty statement
                                   {cancel + $1 + force }
             | BEG stmt_list END   // a block
                            { $1 + indent + force + $2 +
                              cancel + outdent + force + $3 }
             | math                // an expression
;
math         : MATH                // build something like an
             | math math           // `expression'
             | simp
             | COLON
             | OPEN decl_list CLOSE
             | RECORD stmt_list END
;
simp         : SIMP
             | identifier     { "\\\\{" + $1 + "}" }
;
identifier   : ID_TYPE             // put together identifiers
             | identifier ID_TYPE
;
decl_list    : math                // parameter lists
             | INTRO math                   // for var-parameters
             | decl_list SEMI math    {$1 + $2 + " " + $3 }
             | decl_list SEMI INTRO math    // for var-parameters
;
stmt         : ALPHA math OMEGA stmt  // if then/while do etc.
                                 { $1 + " " + $2 + " " + $3 +
                                   indent + force + $4 + outdent }
             | ALPHA math OMEGA stmt ELSE stmt   // if then else
                           {$1 + " " + $2 + " " + $3 +
                            indent + force + $4 + outdent +
                            force + $5 + indent + force + $6 +
                            outdent }
             | CASE math OMEGA stmt_list END     // case of end
             | BEG stmt_list UNTIL math          // repeat until
                                { $1 + indent + force +
                                  $2 + cancel + outdent + force +
                                  $3 + " " + $4 }
;
proc         : proc INTRO math SEMI   {$1 + $2 + $3 + $4 + force}
             | PROC            // procedure heading
;
stmt         : INTRO math SEMI  // variable and type declarations
                           {$1 + $2 + $3 + force}
;

\end{verbatim}



\subsection{Using the Generated Prettyprinter}

The definitions in the previous section are sufficient to produce
a prettyprinter for \PASCAL, that can handle most of the language
features and formats them to suit my own preferences. As an example
text I have chosen a simple \PASCAL\ routine to compute the
square root of a given real number. It was written solemly for
pleasure in my first year of study in Darmstadt to test one of
the algorithms that were presented in a maths lecture. This
is to demonstrate, that the example is by no means constructed
to suit the demonstration purpose in this paper. I have
tested the prettyprinter on various other \PASCAL\ texts.

\index{pascal@\PASCAL}\index{Darmstadt}


\subsubsection{The Pascal Input}

This is what the plain \PASCAL\ source code looks like.

\begin{verbatim}
function Wurzel ( x : REAL ) : REAL;
{Berechnet die positive Quadratwurzel von x}
var x0, x1 : real;
begin
if x>=0 then begin
             x1:=x;
             repeat
               x0:=x1;
               x1:=(x0+x/x0)/2;
             until (x0 + abs(x0-x1) = x0);
             Wurzel:=x1;
             end
        else begin
             writeln('Fehler: Wurzel ist komplex!');
             end;
end; {Wurzel}
\end{verbatim}


\subsubsection{The Translation in \TeX}

This is what the prettyprinter generated out of the \PASCAL\ text.
Note again that the format commands are translated to suit the \t{cwebmac}
macro package of the \CWEAVE\ system. The commands outside of the
indicated area necessary to put \TeX\ into the right mood to format
source code. The control sequences \verb|\1|\dots\verb|\7| refer to
\fmt{indent} (1), \fmt{outdent} (2), \fmt{opt} (3, with the digit $n$
following directly), \fmt{backup} (4), \fmt{break\_space} (5),
\fmt{force} (6) and \fmt{big\_force} (7). The commands \verb|\\| and
\verb|\&| tag identifiers and reserved words, respectively.


\begin{verbatim}
\input cwebmac
\B
\Y
% generated text begins here
\7\4\&{function} \\{Wurzel}(\\{x}:\&{real}):\&{real};
\C{{Berechnet die positive Quadratwurzel von x}}\6\4\&{var}
\\{x0},\39\\{x1}:\&{real};\6
\&{begin}\1\6\&{if} \\{x}$\geq$0 \&{then}\1\6
\&{begin}\1\6\\{x1}:=\\{x};\6\&{repeat}\1\6\\{x0}:=\\{x1};
\6\\{x1}:=(\\{x0}+\\{x}/\\{x0})/2;\2\6\&{until}
(\\{x0}+\\{abs}(\\{x0}-\\{x1})=\\{x0});\6\\{Wurzel}:=\\{x1};
\2\6\&{end}\2\6\&{else}\1\6
\&{begin}\1\6\&{writeln}('Fehler: Wurzel ist komplex!');
\2\6\&{end}\2;\2\6\&{end};\C{{Wurzel}}
% generated text ends here
\end
\end{verbatim}


\subsubsection{The Formatted Output}

This is what the actual formatted output looks like, if the above
text is processed by \TeX.

\begin{outp}

% \1 indent
% \2 outdent
% \3 opt
% \4 backup
% \5 break_space
% \6 force
% \7 big_force
% \8 no_indent
% \& \res
% \\ \id

%

\myforce\mybackup\res{function} \id{Wurzel}(\id{x}:\res{real}):\res{real};
\{Berechnet die positive Quadratwurzel von x\}
\myforce\mybackup\res{var}
\id{x0}, \id{x1}:\res{real};\myforce
\res{begin}\myindent\myforce\res{if} \id{x}$\geq$0 \res{then}\myindent\myforce
\res{begin}\myindent\myforce\id{x1}\ass\id{x};\myforce\res{repeat}\myindent\myforce
\id{x0}\ass\id{x1};
\myforce\id{x1}\ass(\id{x0}+\id{x}/\id{x0})/2;\myoutdent\myforce\res{until}
(\id{x0}+\id{abs}(\id{x0}-\id{x1})=\id{x0});\myforce\id{Wurzel}\ass\id{x1};
\myoutdent\myforce\res{end}\myoutdent\myforce\res{else}\myindent\myforce
\res{begin}\myindent\myforce\res{writeln}('Fehler: Wurzel ist komplex!');
\myoutdent\myforce\res{end}\myoutdent;\myoutdent\myforce\res{end};\{Wurzel\}

\end{outp}

