----------------------------------------
The Parameter File Library Documentation  
Revised 12/05/01 cates@cs.utah.edu
----------------------------------------

*****************************
THE SHORT FORM  -- START HERE
*****************************

Create parameter files (ascii text) like this:

 (parameter_name value1 value2 ... ) // comments

For example:

 // HERE IS A SAMPLE PARAMETER FILE
 (param_with_no_values)  // comments
 (boolean_param 0)
 (float_param 0.0)
 (integer_param -1)
 (list_of_floats 0.0 1.0 5.0)  // blah blah
 (file_name "output.bin")
 (mixed_param "text" 1 0.0)


Read parameter files like this:

#include "param.h"

main() 
{
 int integer_param;
 float several_floats[2];

 VPF::ParameterFile pf;
 pf.Initialize("filename");

 VPF::set(integer_param, pf["integer_param"][0]);
 VPF::set(several_floats[0], pf["list_of_floats"][0]);
 VPF::set(several_floats[1], pf["list_of_floats"][1]);
  
 .
 .
 .

}

Do error checking when you set values like this:

 if (VPF::set(integer_param, pf["integer_param"][0]) == VPF::INVALID)
    {
        std::cerr << "Cannot find integer_param parameter" << std::endl;
        ::exit(-1);
    }

*************************
THE LONG FORM
*************************

I Introduction:  the ParameterFile object

When implementing algorithms, it is often the case that a significant number of
values are needed to initialize various constants, specify input and output
files, or otherwise tune the performance of the algorithm.  Specifying
increasingly more and more parameter values as command line arguments becomes
unwieldy for both the developer and user of the software.  The ParameterFile
object is intended to simplify the process by defining a standard file format
to specify parameters and a simple protocol for reading parameter files.

II Implementation

The ParameterFile object encapsulates the process of opening, reading, and
parsing a file into the instantiation of a single high level object with a
limited public interface.  The implementation consists of three components: a
token scanner, a parser, and a syntax tree.  The parser queries the token
scanner for input and constructs a syntax tree of objects whose root node is
the ParameterFile object.

The token scanner yylex() is created using the flex utility, a standard lexical
analyzer generator.  The set of tokens T,

        T = ( identity, string, integer, decimal, rparen, lparen )

recognized by the scanner are encoded in the file param.l as regular
expressions.

The parser is generated with the standard yacc utility and then compiled into a
function yyparse().  When invoked, yyparse() calls yylex() for input and
attempts to identify syntactic structures of the grammar G.

        G = ( V, T, P, ParameterFile)

where V is the set of variables, 

        V = ( ParameterFile, Parameter, Value ), 

and P is the set of productions:

        ParameterFile => Parameter*
        Parameter => lparen identity Value* rparen
        Value => ( string | integer | decimal)

As productions in the grammar are identified, yyparse() constructs a ``syntax
tree'' of objects representing those productions. The tree is constructed by
the parser from the bottom up.  All the objects are subclassed from a pure
virtual VPF::node object, thereby enabling run-time polymorphism of node object
methods.


II Parameter file format

A parameter file as described by the grammar G, is an ASCII text file supplying
a list of parameters of the form,

        (parameter_name optional_value1 optional_value2 ... optional_valueN)

The parameter naming conventions are similar to C language variable naming
conventions.  A parameter name must begin with an alphanumeric character and
may consist of any of the letters A-Z, a-z; numbers 0-9; and the underscore
character _ .

The optional values may be either integer, decimal, or string values.  Decimal
numbers can be either floating point or double precision.  Some variants on
these types are also supported (long double, etc).  Check the header files for
a complete list of types supported (or add your own).  A number value lacking a
decimal point character is assumed to be an integer value. (There is no good
reason for this and it can be easily fixed by overriding the Set methods
appropriately.)

A string value is specified by enclosing any characters (except the newline and
" characters) in quotation marks ".

        (parameter_name "string value number 1.1" "stri%$ng value number 2")

The value types for a parameter can be mixed.  For example,

        (mixed_values  45.23 1 0 2 3234.99999 "string")

C++-style commenting is supported.  C-style commenting is not supported.  All
characters after double forward slashes // up to a newline character are
ignored.


III The ParameterFile object

The ParameterFile object is a ``nice'' object, meaning that the copy
constructor and assignment operators are defined to perform deep copies.
Instances of ParameterFile objects can be safely passed by reference or by
value.

A ParameterFile object can be instantiated with a character string, a copy
constructor, or by assignment,

        VPF::ParameterFile p1("filename");  // filename
        VPF::ParameterFile p2(p1);          // copy constructor
        VPF::ParameterFile p3;  p3 = p2;    // assignment

Note the use of the scope resolution operator.  The ParameterFile objects are
enclosed in a namespace VISParameterFile aliased to VPF.

When instantiated with a character string argument, the constructor attempts to
open and parse the file whose name is represented in the argument, calling the
yyparse() method.  On success, a pointer to the resulting syntax tree is held
in the ParameterFile object.

The ParameterFile object contains the following public methods:

 bool valid()   Returns true if object contains a valid syntax tree and
                false otherwise.
 int size()     Returns the number of parameters contained in the syntax
                tree.
 bool empty()   Returns true if the object's valid syntax tree is empty and
                false otherwise.
 void clear()   Clears the syntax tree and frees all associated memory.
 void print()   Prints a formatted list of everything in the syntax tree
                to standard out.

The syntax tree of the ParameterFile object can be thought of as an ordered
list of Parameter objects.  The [] operator has been overloaded to allow (read)
access to the parameters.  Supplying an integer argument i returns the i'th
parameter in the list, as ordered in the input file.  No bounds checking is
performed by this operation. Supplying a character string argument returns the
the parameter whose name matches the argument.  If no match is found, a ``null
parameter'' is returned whose validity is false (see next section).


IV The Parameter object

A Parameter object is also a ``nice'' object in the sense that it can be passed
by value or reference and its assignment operator is overloaded.

A Parameter object has the following methods:

 bool valid()   Returns true if the parameter is valid, false otherwise.
 int size()     Returns the number of values contained in the parameter.
 bool empty()   Returns true if the object's value list is empty, false
                otherwise.
 const char *getName()  Returns the name of the parameter.
 void print()   Prints the parameter name and its values to standard out.  

A Parameter object contains a character string name and an ordered list of
Value objects.  The [] operator has been overloaded to allow (read) access to
this list. No bounds checking is performed by the [] operator.  Note that since
a Value object may be of several types, the assigment operator cannot be
overloaded for the Value object.  Hence the value contained in the object can
only be accessed by downcasting to the appropriate class and using that class's
getValue method.  The preferred method for accessing a value is through the
overloaded set method described in the next section.


V The set method

The VPF::set method has been overloaded for all the supported variable types.
It takes as its arguments a variable of the appropriate type and a Value
object and returns VPF::VALID if the operation was successful and VPF::INVALID
otherwise.  The declaration of the set method has the following form: 

        VPF::ReturnStatusType set(<variable type> &, VPF::Value &)

The method works by first checking the type of the supplied Value object to
make sure it is consistant with the requested variable type.  Then the value
contained in the Value object is cast to the appropriate type and the
assignment is made.
