MPQC 2.3.1

- Main Page
- Related Pages
- Classes
- Files

The KeyVal Library

The KeyVal class provides a means for users to associate keywords with values.

ParsedKeyVal is a specialization of KeyVal that permits keyword/value associations in text such as an input file or a command line string.

The package is flexible enough to allow complex structures and arrays as well as objects to be read from an input file.

- Assignment
- Keyword Grouping
- Array Construction
- Table Construction
- Expression Evaluation
- Objects

## Assignment

As an example of the use of ParsedKeyVal, consider the following input:

    x_coordinate = 1.0
    y_coordinate = 2.0
    x_coordinate = 3.0

Two assignements will be made. The keyword `x_coordinate` will be associated with the value `1.0` and the keyword `y_coordinate` will be assigned to `2.0`. The third line in the above input will have no effect since `x_coordinate` was assigned previously.

## Keyword Grouping

Lets imagine that we have a program which needs to read in the characteristics of animals. There are lots of animals so it might be nice to catagorize them by their family. Here is a sample format for such an input file:

    reptile: (
      alligator: (
        legs = 4
        extinct = no
        )
      python: (
        legs = 0
        extinct = no
        )
      )
    bird: (
      owl: (
        flys = yes
        extinct = no
        )
      )

This sample illustrates the use of keyword `=` value assignments and the keyword grouping operators `(` and `)`. The keywords in this example are

    reptile:alligator:legs
    reptile:alligator:extinct
    reptile:alligator:legs
    reptile:python:size
    reptile:python:extinct
    bird:owl:flys
    bird:owl:extinct

The `:`'s occuring in these keywords break the keywords into smaller logical units called keyword segments. The sole purpose of this is to allow persons writing input files to group the input into easy to read sections. In the above example there are two main sections, the reptile section and the bird section. The reptile section takes the form `reptile` `:` `(` keyword `=` value assignments `)`. Each of the keywords found between the parentheses has the `reptile:` prefix attached to it. Within each of these sections further keyword groupings can be used, as many and as deeply nested as the user wants.

Keyword grouping is also useful when you need many different programs to read from the same input file. Each program can be assigned its own unique section.

## Array Construction

Input for an array is specified in the input by forming a keyword group. The name of the group is the name of the array and the grouped keywords are the integers , such that , where is the number of elements in the array. For example, an array, called `array`, of length 3 could be given as follows:

    array: (
      0 = 5.4
      1 = 8.9
      2 = 3.7
      )

The numbers `0`, `1`, and `2` in this example are keyword segments which serve as indices of `array`. However, this syntax is somewhat awkward and array construction operators have been provided to simplify the input for this case. The following input is equivalent to the above input:

    array = [ 5.4 8.9 3.7 ]

More complex arrays than this can be imagined. Suppose an array of complex numbers is needed. For example the input

    carray: (
      0: ( r = 1.0  i = 0.0 )
      1: ( r = 0.0  i = 1.0 )
      )

could be written as

    carray: [
      (r = 1.0 i = 0.0)
      (r = 0.0 i = 1.0)
      ]

which looks a bit nicer than the example without array construction operators.

Furthermore, the array construction operators can be nested in about every imaginable way. This allows multidimensional arrays of complicated data to be represented. Here is an example of input for a lower triangular array:

    ltriarray = [ [ 5.4  ]
                  [ 0.0 2.8 ]
                  [ 0.1 0.0 3.7 ] ]

## Table Construction

Although the array construction operators will suit most requirements for enumerated lists of data, in some cases the input can still look ugly. This can, in some cases, be fixed with the table construction operators, `{` and `}`.

Suppose a few long vectors of the same length are needed and the data in the `i`th element of each array is related or somehow belong together. If the arrays are so long that the width of a page is exceeded, then data that should be seen next to each other are no longer adjacent. The way this problem can be fixed is to arrange the data vertically side by side rather than horizontally. The table construction operators allows the user to achieve this in a very simple manner.

    balls: (
      color    = [  red      blue     red   ]
      diameter = [   12       14       11   ]
      material = [  rubber  vinyl   plastic ]
      bounces  = [  yes      no       no    ]
      coordinate = [[ 0.0  0.0  0.0]
                    [ 1.0  2.0 -1.0]
                    [ 1.0 -1.0  1.0]]
      )

can be written

    balls: (
      { color diameter material bounces     coordinate} =
      {  red     12    rubber    yes     [ 0.0  0.0  0.0]
         blue    14    vinyl     no      [ 1.0  2.0 -1.0]
         red     11    plastic   no      [ 1.0 -1.0  1.0] }
      )

The length and width of the table can be anything the user desires.

    Value Substitution

Occasionally, a user may need to repeat some value several times in an input file. If the value must be changed, it would be nice to only change the value in one place. The value substitution feature of ParsedKeyVal allows the user to do this. Any place a value can occur the user can place a `$`. Following this a keyword must be given. This keyword must have been assigned before the attempt is made to use its value in a value substitution.

Here is an example illustrating most of the variable substition features:

    default:linewidth = 130
    testsub: (
      ke: (
        ke_1 = 1
        ke_2 = 2
        ke_3: (
          ke_31 = 31
          ke_32 = 32
          )
        )
      kx = $ke
      r1 = 3.0
      r2 = $r1
      linewidth = $:default:linewidth
      )

is the same as specifying

    testsub: (
      ke: (
        ke_1 = 1
        ke_3: (
          ke_31 = 31
          ke_32 = 32
          )
        ke_2 = 2
        )
      linewidth = 130
      r2 = 3.0
      r1 = 3.0
      kx: (
        ke_1 = 1
        ke_2 = 2
        ke_3: (
          ke_31 = 31
          ke_32 = 32
          )
        )
      )

It can be seen from this that value substitution can result in entire keyword segment hierarchies being copied, as well as simple substitutions.

## Expression Evaluation

Suppose your program requires several parameters `x1`, `x2`, and `x3`. Furthermore, suppose that their ratios remain fixed for all the runs of the program that you desire. It would be best to specify some scale factor in the input that would be the only thing that has to be changed from run to run. If you don't want to or cannot modify the program, then this can be done directly with ParsedKeyVal as follows

    scale = 1.234
    x1 = ( $:scale *  1.2 )
    x2 = ( $:scale *  9.2 )
    x3 = ( $:scale * -2.0 )

So we see that to the right of the `<tt>=</tt>'' the characters` `(`'' and ```)`'' are the expression construction operators. This is in contrast to their function when they are to the left of the ```=`'', where they are the keyword grouping operators.

The expression must be binary and the data is all converted to double. If you use the expression construction operators to produce data that the program expects to be integer, you will certainly get the wrong answers (unless the desired value happens to be zero).

## Objects

An instance of an object can be specified by surrounding it's classname with the `<tt><</tt>'' and``>`'' operators immediately after the keyword naming the data.

A pointer to a single object can be associated with multiple keywords by using value substitution. This is accomplished by holding references to all objects once they are read in.

Consider a linked list class, A, which reads from the keyword `next` a reference to an object of class A. Input for such an object, read from keyword `a1`, follows:

    a1<A>: (
        next<A>: (
            next<B>: (
                bdata = 4
                next<A>:()
                )
            )
        )
    a2 = $:a1

The `a1` list would contain two `A` objects followed by a `B` object followed by another `A` object. The `a2` list refers to exactly the same object as `a1` (not a copy of `a1`).