% This is a file written using noweb
%
% $Id: attr.nw,v 2.0 1996/12/16 17:04:57 gaertner Exp $
%

\documentclass{article}
\usepackage{a4,pretzeldoc,version,noweb}
\begin{document}

\includeversion{bigspecs}
%\includeversion{impls}
%\excludeversion{bigspecs}% without elaborate specification
\excludeversion{impls}% without implementation



\title{The Attribute Class}
\author{Felix G\"artner}
\maketitle


\begin{abstract}
    This text introduces a new \CPP\ class called [[Attribute]] that
    implements attributes for an attribute grammar used for
    prettyprinting programming language source code.
\end{abstract}


\tableofcontents


\section{Introduction to the Attribute Class}

The following sections describe the
\begin{bigspecs}elaborate\end{bigspecs} specification \begin{impls}and
  implementation\end{impls} of a new \CPP\ class called [[Attribute]].
It was designed as part of a project to build a program that should
produce a general purpose prettyprinter from a formal specification of
a programming language. This class is used in the generated
prettyprinter to accompany the parsing and build up the prettyprinted
output.

<<header>>=
#ifndef ATTR_H
#define ATTR_H

<<Header files to include in the specification>>
<<Macro definitions in the specification>>

<<The [[Attribute]] class declaration with its subclasses>>
<<Declarations of functions to handle attributes>>

#endif

@

\begin{impls}
  The implementation of the class will be described simultaneously
  with the presentation of the specification. The implementation will
  start off from this noweb chunk.

<<implementation>>=
#include"attr.h" /* include own header */

<<Header files to include in the implementation>>

<<Implementation of the [[Attribute]] class and its subclasses>>
<<Implementation of the functions that handle attributes>>

@

\end{impls}

The rest of this text will contain:

\begin{itemize}
  \begin{bigspecs}
  \item A section containing a first look at the general idea of
    parsing with attribute grammars.
  \end{bigspecs}
\item A general overview over the class interface.
\item A detailed description of the class interface\begin{impls}
    together with its implementation\end{impls}.
  \begin{bigspecs}
  \item Finally, a few examples for using attributes are given.
  \end{bigspecs}
\end{itemize}



\begin{bigspecs}

\section{Parsing with Attribute Grammars}

Attribute grammars are a common subject in today's world of computer
science. They are used heavily in compilers to generate a machine
internal representation of the syntax of a given programming
language. The general idea of an attribute grammar is that every
grammar token has an associated value (an {\em attribute}) attached to
it. If a grammar rule fires, then the attribute value of the new token
is found by putting together the attributes of the reduced tokens
accoring to a set of rules, that are seperate from the grammar.  These
attribute rules form a second set of rules that accompany the grammar
rules. This changes a normal formal grammar into an attribute grammar.

The object class presented in this text is a realization of such
attributes. These attributes were written to work together with a
simple parser generated by a parser generator. Attributes can be
created (e.g.~when terminal tokens are processed) and existing
attributes can be formed into a new attribute by joining them together
(e.g.~when a grammar rule fires). In this way the parser generates an
``attribute image'' of the parsed text that reflects the syntax of the
source text, but doesn't necessarily have to look like the syntax tree
that is implicitly defined by the grammar rules that the parser
chooses.

The attributes that are specified here are specialized for their only
task of prettyprinting. They can basicly hold strings or
format commands. Format commands can be viewed as a small set of
simple typesetter commands (like ``begin a new line''). They are
explained in more detail in the specifications of the [[Output]] class
that is also part of this project. For short simply think of format
commands as an instance of an enumeration type.

\end{bigspecs}



\section{Specification Overview for Attributes}

\begin{bigspecs}

The [[Attribute]] class consits of one abstract base class and three
derived subclasses. Why three? Well, of course there have to be at
least two subclasses, i.e.~instances of attributes that are strings
and others that are format commands. They are called [[Text_attribute]]
and [[Format_attribute]]. The third subclass is called [[Attributelist]]
and contains a list of [[Attribute]]s (so the members of such a list can
be any type of attribute, especially [[Attributelist]]s again!). This
allows putting together attributes easily when new attributes have to
be created.  So an [[Attribute]] can be adjoined with other attributes
to become a new, larger attribute. Thus, attributes can be of
arbitrary size.

\begin{figure}
  \begin{center}
    \leavevmode
\setlength{\unitlength}{0.012500in}%
\begin{picture}(205,81)(8,708)
\thinlines
\put( 90,757){\line( 2, 1){ 28}}
\put(131,771){\line( 0,-1){ 49}}
\put(145,771){\line( 4,-3){ 32}}
\put( 45,779){\makebox(0,0)[b]{abstract base class}}
\put(105,776){\framebox(58,13){}}
\put(134,780){\makebox(0,0)[b]{[[Attribute]]}}
\put(130,712){\makebox(0,0)[b]{[[Attributelist]]}}
\put( 30,724){\makebox(0,0)[b]{derived}}
\put( 29,708){\makebox(0,0)[b]{subclasses}}
\put( 84,745){\makebox(0,0)[b]{[[Format_attribute]]}}
\put(180,736){\makebox(0,0)[b]{[[Text_attribute]]}}
\end{picture}
  \end{center}
  \caption{Derivation structure of the attribute class.}
  \label{attrfig}
\end{figure}


The derivation structure from the previous section suggests that we
have to deal with four different classes here, three of which are
derived from the first. This base class is the [[Attribute]] class.  Use
it if you're not sure about the actual type of attribute that you are
going to use. Also, you can use any subclass object in its place,
i.e.~if an [[Attribute]] type object is required, you can use a
[[Text_attribute]] or [[Format_Attribute]].

\end{bigspecs}


To build attributes while parsing with an attribute grammar, there are
two main functions that do the job. The first one creates an attribute
from a string or format command. The second one joins two attributes
together and forms a new attribute consisting of these two. Table
\ref{tab:usage} gives an overview over the usage:

\begin{table}[htbp]
  \begin{center}
    \leavevmode
    \begin{tabular}{ll}
      [[create(char* s)]] & $\longrightarrow$ [[Attribute*]] \\
      [[create(const char* s)]] & $\longrightarrow$ [[Attribute*]] \\
      [[create(Format_command f)]] & $\longrightarrow$ [[Attribute*]] \\
      [[join(Attribute* a1, Attribute* a2)]] & $\longrightarrow$
      [[Attribute*]] \\
    \end{tabular}
    \caption{Overview over attribute manipulation commands.}
    \label{tab:usage}
  \end{center}
\end{table}


Note that they are simple global functions and not member functions of
the attribute class. They are simply shorthands for invocations of
[[Attribute]] member functions and so belong to the ``attribute
toolbox'', as you might say.

Note also that all functions return pointers to attributes. This
allows efficient implementation. The [[join]] function also takes
pointers to attributes, so you can simply say
$$\hbox{[[a=join(create("foo"),create("bar"));]]}$$ to create an
attribute that contains the two texts ``foo'' and ``bar''.

As the above functions are enough to deal with attributes,
we'll only mention a third handy funtion here that you might need.
It can be used to output the contents of an attribute to an output
stream.

\begin{center}
  \begin{tabular}{ll}
    [[print( Output& otp )]] & $\longrightarrow$ [[void]] \\
  \end{tabular}
\end{center}

From the three functions it is the only member function of the
attribute class. So, say you have an existing attribute $a$ and you
want to look what's inside, you simply have to call
$$\hbox{[[a.print(outp);]]}$$ and it will send the contents of the
attribute to the given output object. If you don't know, what such an
object is, read the specifications of the output class, that also is
part of this project. For the time being you can think of an output
object as an output stream, that does automatic handling of format
commands.




\section{Specification Details for Attributes}

Now that we've seen an overview, we can go for the rest of the
goodies.


\subsection{Details of [[Attribute]]}

Here is the declaration of the abstract base class
[[Attribute]]. The abstract base class defines two virtual member
functions, that are automatically inherited by its subclasses.

\begin{enumerate}
\item The first member function is a simple constructor that takes an
  initializing value as parameter.
\item The second member function is called [[print]] and is used to
  output the contents of an attribute. This is done using an object of
  type [[Output]], that was specially designed for outputting
  attributes to an output stream.
\end{enumerate}

For this reason we mustn't forget to include the output class here.

<<Header files to include in the specification>>=
#include"output.h"

@ Though I am not quite happy with ``[[print]]'' as name of the
outputting function, I'll stick with it now. Maybe it would be nice
to use an overloaded insertion operator `[[<<]]' for the output of an
attribute to an [[Output]].

<<The [[Attribute]] class declaration with its subclasses>>=
class Attribute {
public:
    Attribute(); /* The constructor */
    virtual ~Attribute() { }  /* The destructor */
    virtual void print(Output&) = 0; /* The output function */
};

@

\begin{impls}

  The abstract base class [[Attribute]] is quite easy to implement. As
  the [[print]] function is declared virtual, only the constructor needs
  to be implemented. We won't use the constructor for the abstract
  base class and I'm not sure if this even is allowed. So the final
  implementation of the function is empty.

<<Implementation of the [[Attribute]] class and its subclasses>>=
Attribute::Attribute()
{
        /* empty! */
}

@

\end{impls}




\subsection{Details of [[Text_attribute]]}

We have seen that there are three subclasses of the abstract base
class [[Attribute]]. Let's look at the derived class [[Text_attribute]]
first.

A [[Text_attribute]] handles a simple string, that is text in \C\
terms. The string is copied into the attribute so you can safely
re-use the character pointer that you pass on to the [[create]]
function after creation. \begin{impls}The string is hidden as a
  private member inside the body of the attribute.\end{impls} The
contents of this string can only be changed once, that is during the
creation of the attribute. So you can say for instance:
$$\hbox{[[Text_attribute ta="some text";]]}$$ and you will get an
attribute that handles the specified string internally.

<<The [[Attribute]] class declaration with its subclasses>>=
class Text_attribute : public Attribute {
public:
    Text_attribute(const char*);
    void print(Output&);
    ~Text_attribute();
private:
    TEXT_ATTRIBUTE_CONTENTS contents;
    // for safety:
    Text_attribute();
    Text_attribute(const Text_attribute&);
    const Text_attribute& operator=(const Text_attribute&);
};

@

The [[TEXT_ATTRIBUTE_CONTENTS]] are opaque within the specification.
Consider them to be a [[void*]].

\begin{impls}
  The contents are really a \C\ string. But this is only known to the
  reader of the implementation (though it shows in the extracted
  header file). With this definition of the
  [[TEXT_ATTRIBUTE_CONTENTS]] macro the private member [[contents]]
  becomes a [[char*]] \C\ string.

<<Macro definitions in the specification>>=
#define TEXT_ATTRIBUTE_CONTENTS char*
@

The constructor for a [[Text_attribute]] allocates new memory for the
string it is destined for and copies this string into it's own memory.
Care is taken that allocation actually takes place.

<<Implementation of the [[Attribute]] class and its subclasses>>=
Text_attribute::Text_attribute(const char *z)
{
        int len = strlen(z);
        contents = new char[len+1]; /* allocate new storage */
        assert(contents != 0); /* check if memory has run out */
        strcpy(contents,z); /* store the string */
}

@ Of course we need the {\tt assert.h} and the {\tt string.h} headers
to do this.

<<Header files to include in the implementation>>=
#include<assert.h>
#include<string.h>

@ Implementing the [[print]] function is very simple because the
problem of printing is handled by the [[Output]] object handed over to
[[print]]. See the specifications of the [[Output]] class for details.
We can't just send the string to an output stream, because format
commands (see below) have to be interpreted too.

<<Implementation of the [[Attribute]] class and its subclasses>>=
void
Text_attribute::print(Output& out)
{
        out.do_output(contents);
}

@

The destructor simply releases any memory allocated for the
[[contents]].

<<Implementation of the [[Attribute]] class and its subclasses>>=
Text_attribute::~Text_attribute()
{
	delete contents;
}
@

\end{impls}





\subsection{Details of [[Format_attribute]]}

The main type of attributes you will use will be text attributes that
have been described in the preceding subsection. The other type of
attributes are called format attributes and contain a so called {\em
  format command}. Format commands influence the way, in which the
generated code is output by the [[Output]] type object and the
typesetter. For details please see the main part of the documentation
of the project or the specifications of the output class. Attributes
that store format commands are objects of the class
[[Format_attribute]].

Format attributes store a format command. Format commands are of type
[[Format_command]].  This type is declared as part of the output class
header file that has been included earlier.

<<The [[Attribute]] class declaration with its subclasses>>=
class Format_attribute : public Attribute {
public:
    Format_attribute(Format_command); /* constructor */
    void print(Output&);
    ~Format_attribute();
private:
    FORMAT_ATTRIBUTE_CONTENTS contents;
    // for safety:
    Format_attribute();
    Format_attribute(const Format_attribute&);
    const Format_attribute& operator=(const Format_attribute&);
};

@

The private contents of format attributes are opaque. Consider them
to be a [[void*]].

\begin{impls}

  If you look at the implementation, the contents are in fact a simple
  [[Format_command]]. This turns the private member [[contents]] into
  a format command accessible by the member functions.

<<Macro definitions in the specification>>=
#define FORMAT_ATTRIBUTE_CONTENTS Format_command
@

  From the previous chunk it is clear, that instead of
  storing a string (like the text attribute does) a format attribute
  stores a format command. Such a command normally can be represented
  by a single integer (as an enumeration type) and so the
  implementation of [[Format_attribute]] is even simpler than that of
  [[Text_attribute]] in that no memory allocation has to take place.
  (For more information on format commands confer
  the specifications of the [[Output class]].)

<<Implementation of the [[Attribute]] class and its subclasses>>=
Format_attribute::Format_attribute (Format_command f) : Attribute ()
{
        contents = f; /* store the format command */
}

@ The [[print]] function is as simple as above.

<<Implementation of the [[Attribute]] class and its subclasses>>=
void Format_attribute::print(Output& out)
{
        out.do_output(contents); /* output the format command */
}

@ The destructor is empty, since a format command doesn't contain
any memory from the heap.

<<Implementation of the [[Attribute]] class and its subclasses>>=
Format_attribute::~Format_attribute()
{
}

@


\end{impls}



\subsection{Details of [[Attributelist]]}

Here comes the interesting bit of the [[Attribute]] class, namely the
subclass [[Attributelist]]. Simply spoken, an [[Attributelist]] is a list
of attributes. But an [[Attributelist]] is itself an attribute again,
so an [[Attributelist]] object can itself appear as a link in the chain
of attributes again. Got it?!

This subclass is the only one to have more public members as the
others. Of course there are again the constructor (that takes an
attribute and creates a list with one element); we have again the
[[print]] member function to output the contents of the list to an
[[Output]] class object. But there is also a new function [[append]] that
takes an attribute and appends it to the current list of attributes.

<<The [[Attribute]] class declaration with its subclasses>>=
class Attributelist : public Attribute {
public:
    Attributelist(Attribute*); /* constructor */
    void print(Output&); /* outputs a list of attributes */
    void append(Attribute*); /* appends an attribute to the list */
    ~Attributelist();
private:
    ATTRIBUTELIST_CONTENTS contents;
    // for safety:
    Attributelist();
    Attributelist(const Attributelist&);
    const Attributelist& operator=(const Attributelist&);
};

@ The contents of the [[Attributelist]] are opaque. Consider them to
be a [[void*]].

\begin{impls}

  Looking at the implementation, you'll see that the contents of an
  [[Attributelist]] are in fact two things: A pointer to an
  [[Attribute]] which is one element of the list and a pointer to
  another [[Attributelist]]. From this we see that the subclass
  implements a simple linked list.

<<Macro definitions in the specification>>=
#define ATTRIBUTELIST_CONTENTS struct {                          \
    Attribute* listenelement; /* contents of this link */        \
    Attributelist *next; /* pointer to the rest of the list */   \
    }

@

The main task of implementing the type [[Attributelist]] is the
implementation of a simple linked list. The constructor creates a
list of one element and sets the [[next]] pointer to [[NULL]].

<<Implementation of the [[Attribute]] class and its subclasses>>=
Attributelist::Attributelist(Attribute* a) : Attribute ()
{
        contents.listenelement = a;
        contents.next=NULL;
}

@ The [[print]] routine runs through the list and calls the [[print]]
function of every subsequent element of the attribute list. It would
be nice to have a recursive version of this function, but this turns
out to be quite difficult. You would need a seperate recursive function
that takes a list as argument, wouldn't you? The [[this]] pointer is
an implicitly defined pointer to the current object whose member
function you are currently using. This instance of the [[print]] member
function actually ensures that the ``tree'' of attributes is
traversed completely when doing [[print]].

<<Implementation of the [[Attribute]] class and its subclasses>>=
void Attributelist::print(Output& out)
{
        for (Attributelist *i=this; i!=NULL ; i=i->contents.next)
        {
            i->contents.listenelement->print(out);
        }
}

@ Here is the implementation of the [[append]] member function. It is a
recursive function that appends an attribute [[a]] to the current list.
If this list (where [[a]] should be appended) is empty, it creates a
new list node and sets the contents of this node to [[a]]. The [[next]]
pointer of the current list is then pointed to the adress of this new
list node.

If the list (where [[a]] should be appended) is not empty, [[a]] is
appended to the list that is pointed to by the [[next]] pointer.

<<Implementation of the [[Attribute]] class and its subclasses>>=
void Attributelist::append(Attribute *a)
{
        if (contents.next!=NULL)
        {
                contents.next->append(a);
        }
        else
        {
                Attributelist *neu = new Attributelist ( a );
                assert(neu!=0);
                contents.next=neu;
        }
}

@ An [[Attributelist]] contains a pointer to an Attribute (which are
the real contents of this list item) and a ``next''-pointer to the
following list item (or a [[NULL]] pointer if it's the last item on
the list). So the desctructor doesn't have to free any allocated
storage, but it has to take care that the {\em entire} list is
destroyed. The way to do it is to destroy the following list first
before itself is enters the graveyard.

<<Implementation of the [[Attribute]] class and its subclasses>>=
Attributelist::~Attributelist()
{
	if (contents.next != NULL) {
		delete contents.next;
	}
}

@


\end{impls}





\subsection{Details of Functions to Handle Attributes}

All actions on attributes (creating them and joining them together to
form new ones) can be performed using two overloaded functions. These
functions are called [[create]] and [[join]] and will be presented in this
section. So forget about constructors and private members of normal
attributes. The only things you should remember are what attributes
are and how the following two functions work.

The first useful function to handle attributes is called [[create]]
and does nothing but to, well, ``create'' an attribute. You can pass
either a simple string to this function or a format command name and
the function will return a pointer to the attribute containing the
passed information. The storage space connected with this attribute is
allocated dynamically and will not be deleted until the program using
this function terminates. Since some systems don't free the dynamic
memory when a program exits this doesn't make sense. This might be a
point for future work.

So here is the function that creates an attribute from a
string.

<<Declarations of functions to handle attributes>>=
Attribute* create (const char *);
Attribute* create (char *);
@

\begin{impls}

Here is the code implementing the first instance of the |create|
function. Called with a string, [[create]] creates a
[[Text_attribute]].

<<Implementation of the functions that handle attributes>>=
Attribute* create (const char *z)
{
        Text_attribute *t = new Text_attribute(z);
        return t;
}
Attribute* create( char* z )
{
        Text_attribute *t = new Text_attribute(z);
        return t;
}
@

\end{impls}

The next instance of [[create]] is for format commands.

<<Declarations of functions to handle attributes>>=
Attribute* create (Format_command);
@

\begin{impls}
  In the implementation, called with a format command, the function
  creates a [[Format_attribute]]. In both cases a pointer to this
  attribute is returned.

<<Implementation of the functions that handle attributes>>=
Attribute* create (Format_command i)
{
        Format_attribute *f = new Format_attribute(i);
        return f;
}
@

\end{impls}

For example, now you can say
 %
\begin{quote}
  [[Attribute *a;]]\par
  [[a=create("any text\n");]]\par
\end{quote}
 %
or
 %
\begin{quote}
  [[Attribute *b = create(force);]]\par
\end{quote}
 %
where [[force]] is the name of a format command. These two examples
will create an attribute [[a]] that holds the text line ``any text''
(and a newline) and an attribute [[b]] that contains the format
command [[force]].

\begin{impls}
It is important to know that the [[create]] function that takes a string
invokes the constructor for [[Text_attribute]] and thus the given string
is implicitly copied into the attribute itself. So:
\end{impls}
You can safely re-use the string pointer passed as an argument to
[[create]].

\medskip

The next and final function to handle attributes is called
[[join]].  With this function you can, well, join two attributes
together forming a new attribute. \begin{impls}Actually an attribute list
containing these two attributes is created. But an attribute list is
again an attribute \ldots\end{impls}

First have a look at the [[join]] function with two arguments.

<<Declarations of functions to handle attributes>>=
Attribute*
join(Attribute *a1, Attribute *a2);

@

So if you have two attributes (as pointers), say [[a]] and [[b]], you
can build a new attribute [[c]] by simply saying
 %
\begin{quote}
  [[c=join(a,b);]]
\end{quote}


\begin{impls}
  If you look at the implementation of [[join]], you will notice, as
  this attribute [[c]] is actually an attribute list (but nevertheless
  an attribute), [[c]] is also allocated once and for all and will
  never be deleted unless the program terminates.

  Here's the implementation: Called with two parameters [[a]] and
  [[b]], [[join]] simply creates an attribute list with [[a]] and
  appends [[b]] to it.

<<Implementation of the functions that handle attributes>>=
Attribute* join (Attribute *a1, Attribute *a2)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    l->append(a2);
    return l;
}

@

\end{impls}

@ However, instead of joining two attributes together, you can also
join three, four, five, \dots, and up to ten different attributes
together with the same function. Since the following definitions are
nearly all the same, feel free to skip the following text until the
next section begins.

<<Declarations of functions to handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8,
        Attribute *a9);

Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8,
        Attribute *a9, Attribute *a10);

@ If anybody knows a way to get around this way of defining this
thing, I'd be grateful for a short notice.

\begin{impls}
  The implementation of the [[join]] is possibly the trickiest thing
  in this whole document. A first idea would be to implement all the
calls of [[join]] with more than 2 arguments in a way that relies on the
version with two arguments. This means that a call of
$$\hbox{[[join(a1,a2,a3);]]}$$ would be done by first calling a joining
operation on the first two arguments and then joining the result of
this first operation with the last attribute, i.e. doing:
$$\hbox{[[join(join(a1,a2),a3);]]}$$ This however would result in
attribute trees that look like binary trees and would create
``deeper'' trees that also consume more memory, because you need more
``nodes'' in your tree.

The goal in the current implementation is to raise the branching factor
of the trees to minimize the depth. This is done by making the lists
of attributes longer. Always going back to the simple [[join]] function
would always result in lists of maximum length 2. Here we`ll try to
raise the maximum to something around 10.

<<Implementation of the functions that handle attributes>>=
Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2]] and [[a3]] to [[l]]>>
    return l;
}
@

We'll use a nice trick to spare us typing the stuff in again and
again. The {\tt noweb} system allows us to re-use section code. The
following code is part of all subsequent [[join]] implementations.

<<Append [[a2]] and [[a3]] to [[l]]>>=
l->append(a2);
l->append(a3);
@

<<Implementation of the functions that handle attributes>>=
Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3]] and [[a4]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3]] and [[a4]] to [[l]]>>=
<<Append [[a2]] and [[a3]] to [[l]]>>
l->append(a4);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4]] and [[a5]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4]] and [[a5]] to [[l]]>>=
<<Append [[a2, a3]] and [[a4]] to [[l]]>>
l->append(a5);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4, a5]] and [[a6]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4, a5]] and [[a6]] to [[l]]>>=
<<Append [[a2, a3, a4]] and [[a5]] to [[l]]>>
l->append(a6);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4, a5, a6]] and [[a7]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4, a5, a6]] and [[a7]] to [[l]]>>=
<<Append [[a2, a3, a4, a5]] and [[a6]] to [[l]]>>
l->append(a7);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4, a5, a6, a7]] and [[a8]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4, a5, a6, a7]] and [[a8]] to [[l]]>>=
<<Append [[a2, a3, a4, a5, a6]] and [[a7]] to [[l]]>>
l->append(a8);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8,
        Attribute *a9)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4, a5, a6, a7, a8]] and [[a9]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4, a5, a6, a7, a8]] and [[a9]] to [[l]]>>=
<<Append [[a2, a3, a4, a5, a6, a7]] and [[a8]] to [[l]]>>
l->append(a9);
@

<<Implementation of the functions that handle attributes>>=
Attribute*
join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4,
        Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8,
        Attribute *a9, Attribute *a10)
{
    Attributelist *l = new Attributelist(a1);
    assert(l!=NULL);
    <<Append [[a2, a3, a4, a5, a6, a7, a8, a9]] and [[a10]] to [[l]]>>
    return l;
}
@

<<Append [[a2, a3, a4, a5, a6, a7, a8, a9]] and [[a10]] to [[l]]>>=
<<Append [[a2, a3, a4, a5, a6, a7, a8]] and [[a9]] to [[l]]>>
l->append(a10);
@

\end{impls}


After testing and using the [[join]] function I have noticed that it
would be very convenient to also have the following function.

<<Declarations of functions to handle attributes>>=
Attribute*
join (Attribute *a1); /* simply returns [[a1]] */
@

\begin{impls}
  This is implemented easily as:

<<Implementation of the functions that handle attributes>>=
Attribute* join (Attribute *a1) {
        return (a1);
}
@

\end{impls}


\begin{bigspecs}

\section{Examples}

Now that we have learned everything about attributes, let's have a
look at a small example how attributes are actually used in the
prettyprinter. This chapter depends heavily on the information of
the main documentation of the ``pretzel'' project. They refer to
the environment in which the attributes of this class are used in
real life. If you have problems understanding this section, then
look there first and return to this text later. But I can already
say that you've learnt everything there is to know about attributes
already and that you might as well skip the rest of this document
without loss of confidence.

Suppose we have a prettyprinting grammar that suffices the demands
described in the main part of the project in the chapter on
file formats (``formatted grammar file''). Say we have a rule
 %
\begin{verbatim}
block : BEGIN stmt_list END
\end{verbatim}
 %
that defines how a statement is formed and say we have a
corresponding rule for creating the attributes like:
 %
\begin{verbatim}
$1 + force + $2 + $3
\end{verbatim}
 %
This will be transformed by the prettyprinter generator into \CPP\
code similar to\par
 \medskip
 \$\$[[=join(]]\$1,[[create(force)]],\$2,\$3);\par
 \medskip\noindent
as code for the action to the rule above in the BISON file.

\end{bigspecs}

\section*{Identifier Index}
\begin{multicols}{2}
\nowebindex
\end{multicols}


\end{document}


%
% $Log: attr.nw,v $
% Revision 2.0  1996/12/16 17:04:57  gaertner
% *** empty log message ***
%
% Revision 1.4  1996/09/02 16:04:06  gaertner
% Added destructor bodies so that g++ won't complain.
%
% Revision 1.3  1996/03/18  11:19:03  gaertner
% The `const' declaration had to be extended to Text_attribute.
%
% Revision 1.2  1996/03/18  11:09:08  gaertner
% Changed declaration of `create' to `create( const char* )' because
% the const is needed when using flex scanner classes.
%
% Revision 1.1  1996/03/07  17:39:28  gaertner
% Initial revision
%
%
%


