DATADEC(L)

NAME
datadec - ANSI C data declaration module constructor

SYNOPSIS
datadec [-vno] basename [infile]

DESCRIPTION
Datadec takes an input file - or stdin if no input file is given - containing a series of HOPE/Miranda style recursive data declarations with optional hints on printing, and builds an definition/implementation pair of ANSI C files - basename.h and basename.c containing data declarations, constructor functions, deconstructor functions and printing functions.

The two files produced together form a module that implements the relevent data types.

OPTIONS

-v  enter verbose mode. Datadec now displays the data types that it parses, along with various almost certainly useless bits of information about optimization.

-n  do not perform various optimizations.

-o  perform optimizations (the default).

AN EXAMPLE

The simplest use is to prepare an input file, such as data.in, which might (for example) contain:
TYPE {
        intlist =  nil or cons( int first, intlist next );
        illist  =  nil or cons( intlist first, illist next );
        idtree  =  leaf( string id )
                or node( idtree left, idtree right );
}
To generate C code implementing these types, invoke:
     datadec eek data.in
which generates eek.h and eek.c

THE DATA DECLARATION LANGUAGE
The language accepted by datadec is split into two components: the "outer language" is patterned after the GMD compiler tools LALR and REX (similar to Yacc and Lex) and allows you to specify four sections (only the last is compulsory):

[ EXPORT { free_format_text } ]
[ GLOBAL { free_format_text } ]
[ BEGIN { free_format_text } ]
TYPE { types }

The contents of the export section are placed in the header file (the .h). Commonly, you may wish to add extern function declarations, public types and external variable declarations which must be placed at the top of the header file, and also define some additional procedures using the automatically generated types which must be placed after the type declarations! To achieve this, you should place a `@@' in the export section -- the text up to that point is placed at the top of the header file, whereas the text after it is placed at the bottom of the header file -- after all the types have been defined.

Similarly, the contents of the global section are placed in the C file, again with `@@' being used to split the global section into "top of file" and "bottom of file" pieces.

Similarly, the contents of the begin section are placed in an initialization procedure, which the user of the constructed module must remember to call at an appropriate juncture (eg. immediately when main starts).

The types section contains the type declarations themselves - the inner language.

The "inner language" - that of specifying the actual types section - is closely modelled on Miranda or Hope, with printing rules added. Here is the grammar:

types	= list(type)
type 	= type_name '=' shape list( 'or' shape ) ';'
shape	= constructor_name [ '(' params ') ] [ print ]
params	= param list( ',' param)
param	= type_name param_name
print	= list(element)
element	= number | string_literal

Note that each data type is terminated by a semicolon, and that (within one data type) each shape is separated from the next by 'or' (just like the '|' in Miranda). If a particular shape has parameters, they are separated from each other by commas. Each type name is simply an identifier.

Datadec also generates routines to write each type to an open FILE *. The method of printing each shape is governed by the presence or absence of a print rule. If no print rule is given, the constructor name is printed, then an open bracket, then each parameter is written out using the appropriate print routine, with commas separating the parameters, then a close bracket.

If a print rule is given, each print element (these are syntactically separated by whitespace) is used to generate the write routine as follows: A literal string will simply be printed (well, '\n' is turned into a newline!), whereas a number (eg. 4) means that the 4th parameter is printed (invoking the print function for that routine).

For example, we could augment the idtree type from the example given above with print rules:
TYPE {
idtree  =  leaf( string id )                    "leaf(" 1 ")"
        or node( idtree left, idtree right )    "node( l=" 1 ", r=" 2 " )";
}

Now, an idtree constructed as
node( leaf( "hello" ), node( leaf( "there" ), leaf( "how are you" ) ) )
would print as:
node( l=leaf("hello"), r=node(l=leaf("there"),r=leaf("how are you")))

SEE ALSO
LALR, REX, Miranda Language Definition.

MISSING FEATURES
I must implement the missing free_TYPE functions sometime.

A cool extra would be a sprint_TYPE function to print into a string. This should be a trivial modification on the code that prints to a file, of course we don't know how long the generated string will need to be.

BUGS
Some single letter typenames (eg. "f" or "p") could clash with internal parameter names in the print routines, leading to syntax errors when you compile the files generated by datadec.

And, finally, one day I'll have to write the C++ and Java versions :-)

AUTHOR
Duncan C. White, D.White@imperial.ac.uk.