NAME
   List::Parseable - routines to work with lists containing a simple
   language

DESCRIPTION
   This module allows you to treat a list (which can be expressed as an
   actual perl list, or as a string which will be parsed to form a list) as
   a simple program which returns a value. This allows you to do several
   tasks that I run into frequently.

   A task that occurs often is to have a config file or a data file which
   is read in by the program. Most of the time, the data stored in these
   files is fully defined at the time it is read in, but occasionally, the
   data that you want is more complex, and is best determined at run time.

   One obvious way to do this is to build extra logic into the program that
   understands the data stored in the file and which can do additional
   operations such as supplying missing values, checking data validity,
   etc., but often, building a knowledge of the exact format of the data
   file is not desired. It leads to added complexity in the program, and
   usually, the types of checks and manipulations that are done are very
   repetitive.

   This module can be used to bypass some of these issues.

   Creating complex values
       If you need to set a variable in a config file or a data file to
       some value which can only be determined at runtime, or which is best
       defined as some definition based on other values is the config file,
       the value can be set to a list which is interpreted using this
       module. That way, the actual value can be determined at runtime
       using a simple program.

   Supplying missing data
       Defaults for missing values can be supplied.

   Describing valid data
       If you want to describe validity checks for data or config files,
       this can be done using this module. A piece of data can be defined
       as well as a flag which will be evaluated based on the value
       currently in the config file. If the data is invalid, the flag will
       be set accordingly.

       A description of the data can be written as a list which, when
       evaluated, will return true if a piece of data meets the validity
       requirements described there.

   All of this could be done by nesting actual perl code and running eval
   on it, but it is usually desirable to do things in a much safer way.
   Also, it is rarely necessary to have the full power (and complexity) of
   the perl language in this case.

ROUTINES
   new
         use List::Parseable;
         $obj = new List::Parseable;

       Creates a new List::Parseable object.

   version
         $version = $obj->version();

       Check the module version.

   list, string
         $obj->list(NAME,LIST);
         $obj->string(NAME,STRING);

       The list function takes the arguments and stores them in the object
       under the given NAME.

       The string function takes a single string argument and converts it
       to a list (string parsing rules are described below).

   eval
         $val = $obj->eval(NAME);

       This must be called after the list or string method is used to store
       a list under the given name. It parses the list using the list
       parsing rules described below.

   errors
         $obj->errors(OPTION,OPTION,...)

       When a list is used in any of the operations described below, some
       of the elements may not be valid for that operation. This option
       tells how to handle these errors. Allowed values for OPTION are:

         exit    : the program halts with an error
         return  : the routine returns an empty set or element
                   (depending on type of return value)
         ignore  : the value is ignored (removed from the list)
                   and the operation continues

       NOTE: exactly one of the above options may be given. It defaults to
       "ignore".

       In addition, the following options may be included:

         stderr   : send a warning about invalid elements to stderr
         stdout   : send a warning about invalid elements to stdout
         both     : sends wanring message to both stdout and stderr
         quiet    : never send warnings

       The default is quiet.

   vars
         $obj->vars(HASH);

       This takes a hash of the form VAR => VAL where each VAR is the name
       of a variable, and each VAL is either a scalar or a list reference
       (which may be nested list references and scalars).

       It stores these in the object for use in the "getvar" and other
       variable operations described below.

LIST PARSING RULES
   List parsing consists of two steps.

   First, every element is examined. If it is a scalar, it is left
   untouched duiring the first step. If it is a list reference, the list of
   values is first parsed using the same rules as the parent list. In this
   way, nested lists are parsed to any level. As an example of this, the
   list:

     (count a b)

   would evaluate to a scalar "2" after the second step (since a list who's
   first element is "count" evaluates to the number of elements in the
   list), so the nested structure:

     (foo (count a b) 3 (count x))

   is identical to:

     (foo 2 3 1)

   after the first step is complete on the main list.

   For the second step of parsing, the list is examined again. It must
   consist of zero or more operations (each of which is one of the strings
   described below) followed by zero or more arguments, each of which can
   be either a list reference or a scalar. The types of arguments allowed
   depend on the operation.

   Arguments start with the first element which is not a known operation.
   Alternately, if one of the elements is "--", that element signals the
   end of the operations and the start of the arguments (but is otherwise
   ignored).

   For example, if "foo" and "bar" are known operations, then

     (foo bar a b)

   has two operations and two arguments. This is equivalent to:

     (foo bar -- a b)

   The list:

     (foo -- bar a b)

   has one operation and three arguments since "bar" is not treated as an
   operation in this case.

   Only the first occurence of "--" are treated this way, and only if it
   follows a set of operations. For example:

     (foo a -- bar b)

   contains one operation (foo) and 4 arguments (a, --, bar, b).

   If no operation is included, it defaults to the "scalar" operation, so

     (scalar a b)
     (a b)

   are equivalent.

   If a list includes multiple operations, they are handled one at a time,
   starting with the right most. For example:

     (foo bar a b)

   is equivalent to:

     (foo (bar a b))

STRING PARSING RULES
   When parsing a string, sets of list delimiters are checked for. Valid
   list delimeters are:

      parenthese ()
      brackets   []
      braces     {}

   The list delimiters may be separated from the list elements by
   whitespace, but this is optional except in cases where the first element
   in the list begins with a punctuation mark. In this case, the list
   delimiter must be followed by space. Any string that starts with a
   punctuation mark which immediately follows the left list delimiter is
   treated as an element delimiter.`q

   Elements in a list are typically separated by spaces, but including an
   element delimiter can change this. An element delimiter is a character
   or string attached to the left list delimiter. The element delimiter
   MUST start some punctuation mark, but it is not allowed to start with
   "\" which is treated specially.

   For example, the list (a b c) can be written in the following ways:

     '( a b c )'
     '(a b c)'
     '[ a b c ]'
     '{: a:b:c }'

   Any combination of list delimiters can be used to create nested lists:

     '(a (b c) [: d:e ] )'

   There is currently no "quoting" mechanism, so there is no way to include
   the element delimiter in an element, so if an element can contain a
   space, some other element delimiter must be used. In other words, to
   make a list: ("this", "is a", "special list"), use:

     '(: this:is a:special list)'

   In order to include any list delimiter in an element, the left list
   delimiter must be followed immediately with an "\". It may then be
   followed by any element delimiter. Everything up to the closing list
   delimiter is treated as part of the list of elements. No nested lists
   can be created. For example:

     '( (a) (\ x ] ) [\: b:) ] )'

   is the list:

     ( [ 'a' ],
       [ 'x', ']' ],
       [ 'b', ')' ] )

   In order to include a parentheses (either left or right) in a list, use
   one of the other list delimiters with the "\" option.

KNOWN OPERATIONS
   In the following operations, lists of elements may be either scalars or
   list references, but in most cases, some types of elements may not be
   valid. In the event of an invalid element, the behavior is dictated by
   the results of the "errors" method.

   The following basic operations are known:

   (scalar ELE0 ELE1 ...), (list ELE0 ELE1 ...)
       These two operations determine how to treat the results of the
       parsing. Most operations take a list of scalars as arguments, but
       some take multiple lists. These require that the "list" operation be
       used.

       For example:

         (foo (scalar a b) (list c d))

       after parsing all of the sublists is eqivalent to:

         (foo a b [ c d ])

       where [ c d ] is a list reference.

       All element types are allowed.

   The following operations take a list and return a scalar based on the
   list:

   (count ELE0 ELE1 ...)
       The count operation counts the number of arguments and returns it.

         (count a b) => 2
         (count (list a b) c) => 2

       All element types are allowed.

   (countval VAL ELE0 ELE1 ...)
       This returns the number of times VAL appears in the list. VAL must
       be a scalar.

         (countval a a b a) => 2

       All elements should be scalars.

   (minval ELE0 ELE1 ...), (maxval ELE0 ELE1 ...)
       This returns the numerical value who's value is the least or
       greatest.

         (minval 5 7 8) => 5
         (maxval 5 7 8) => 8

       All elements should be numeric scalars.

   (nth N ELE0 ELE1 ...)
       This returns the Nth element of the list. Elements are numbered 0 to
       M or -(M+1) to -1.

       The first element must be an integer or nothing is returned. All
       element types are allowed for the remaining arguments.

   (case TEST0 VAL0 ... TESTN VALN [DEFAULT_VAL])
       All TEST elements must be scalars or nothing is returned. Values can
       be any type.

       Tests are evaluated, one at a time, and the first one that evaluates
       as true provides the return value.

       If no test is true, the default value is returned. If no default is
       provided, nothing is returned.

   (indexval VAL ELE0 ELE1 ...), (rindexval VAL ELE0 ELE1 ...)
       This returns the index of the first/last occurence of VAL in the
       list or -1 if it doesn't appear.

       VAL must be a scalar. All other elements should be scalars.

   (join ELE0 ELE1 ...), (join delim DEL ELE0 ELE1 ...)
       This joins all elements into a single string. By default, a space is
       used, but this can be overridden by including the "delim" word as
       the first element in the list followed by the delimiter. DEL can be
       the keywork "_null_" which means to join them with no delimiter,
       "_space_" to join them with a space, or "_nl_" to join them with a
       newline, or "_tab_" to join with a tab.

       DEL must be scalar. All others should be scalars.

   ( + ELE0 ELE1 ...), ( * ELE0 ELE1 ...)
       These return the result of adding or multiplying all of the
       elements.

       All elements should be numbers.

   ( - ELE0 ELE1 ), ( / ELE0 ELE1 )
       These perform the subtraction (ELE0 - ELE1) or division (ELE0/ELE1).
       All elements must be numbers, and in the division case, ELE1 must
       not be zero.

   The following returns true or false (1 or 0) based on the list:

   (mintrue N ELE0 ELE1 ...), (maxtrue N ELE0 ELE1 ...)
       Returns true if at least (or at most) N of the elements evaluate to
       true.

       All elements should be scalars.

   (minfalse N ELE0 ELE1 ...), (maxfalse N ELE0 ELE1 ...)
       Similar to mintrue/maxtrue but tests for false values.

       All elements should be scalars.

   (numtrue N ELE0 ELE1 ...), (numfalse N ELE0 ELE1 ...)
       Returns true if exactly N of the elements evaluate to true (or
       false).

       All elements should be scalars.

   (and ELE0 ELE1 ...)
       Returns true if all elements evaluate to true.

       All elements should be scalars.

   (or ELE0 ELE1 ...)
       Returns true if any element evaluates to true.

       All elements should be scalars.

   (not ELE0 ELE1 ...)
       Returns true if all elements evaluate to false.

       All elements should be scalars.

   (member VAL ELE0 ELE1 ...)
       Returns true if any element in the list is equal to the value.

       All elements should be scalars. The first element MUST be a scalar
       or nothing can be returned.

   (absent VAL ELE0 ELE1 ...)
       Returns true if no element in the list is equal to the value.

       All elements should be scalars. The first element MUST be a scalar
       or nothing can be returned.

   ( ELE0 ELE1 ); also >= == <= < !=>
       This compares ELE0 and ELE1 numerically. It returns true if ELE0 is
       greater than ELE1. The other common mathematcial operations: >=, =,
       <=, <, != are also available.

       Note that space is required after the opening list delimiter in
       order to not confuse them with element delimiters.

       Exactly two numerical elements are required in all cases.

   ( gt ELE0 ELE1 ); also ge eq le lt ne
       This compares ELE0 and ELE1 alphabetically. It returns true if ELE0
       is greater than ELE1. The other common string operations: ge, eq,
       le, lt, ne are also available.

       Exactly two scalar elements are required in all cases.

   (if TEST), (if TEST VAL1), (if TEST VAL1 VAL2)
       This checks to see if TEST evaluates to true. If it is true, it
       returns VAL1 if it is included or true otherwise. If it is false, it
       returns VAL2 if itis include or false otherwise.

       TEST must be a scalar. The other values can be any type.

   (is_equal LIST0 LIST1)
       This takes two list references (which should contain only scalars)
       and checks to make sure that the elements are equal (order is
       ignored). If they are, true is returned. Otherwise, false is.

       If either argument is not a list reference, or if either list
       contains non-scalars, nothing is returned.

   (not_equal LIST0 LIST1)
       Similar to is_equal, but returns true if the two lists are
       different.

   (iff ELE0 ELE1 ...)
       This returns true if all elements are true or all are false. It
       returns false if they are a mixture of true and false.

   (range NUM X Y); also rangeL rangeR rangeLR
       These check to make sure that NUM is in the range X to Y. All three
       must be numeric, and X must be less than (or equal) to Y.

       It returns true in the following cases:

         range    X <= NUM <= Y
         rangeL   X <  NUM <= Y
         rangeR   X <= NUM <  Y
         rangeLR  X <  NUM <  Y

       and false otherwise.

   The following manipulate a list.

   (flatten ELE0 ELE1 ...)
       This takes all elements (which may be scalars or nested list
       references) and returns a flat list with all of the elements from
       any level.

       All element types are allowed.

   (union ELE0 ELE1 ...)
       This combines all of the members of all of the elements (which may
       be scalars or nested lists) into a single list of elements. Only the
       top level is flattened. So:

         (union a [b] [ [c], [d] ]) => (a b [c] [d])

       All element types are allowed.

   (sort ELE0 ELE1 ...)
       This returns the list sorted alphabetically. The list is flattened
       first.

       All elements should be scalars.

   (sort_by_method METHOD LIST ARG1 ARG2 ...)
       This returns the list sorted by the method given. The method can be
       any method in the Sort::DataTypes module. LIST must be a list
       produced by the (list ELE0 ELE1 ...) operation.

       The first element (METHOD) must be a valid method and LIST must be a
       list reference or nothing can be returned. Other arguments must be
       valid for the sort method, but are not checked in advance.

   (unique ELE0 ELE1 ...)
       This removes duplicate elements and returns a list of unique
       elements.

       All elements should be scalars.

   (compact ELE0 ELE1 ...)
       This removes all empty ("") elements and returns a flat list of all
       remaining elements.

       All elements should be scalars.

   (true ELE0 ELE1 ...)
       This removes all elements that evaluate to false and returns a flat
       list of all remaining elements.

       All elements should be scalars.

   (pop ELE0 ELE1 ...), (shift ELE0 ELE1 ...)
       This removes the last/first element from the list and returns the
       resulting list.

       All element types are allowed.

   (pad LENGTH ELE0 ELE1 ...)
       This takes a list of elements and pads it to the right with spaces
       until it is LENGTH characters long. If LENGTH is negative, it will
       pad to the left.

       The first argument must be an integer or nothing will be returned.
       All others should be scalars.

   (padchar LENGTH CHAR ELE0 ELE1 ...)
       This is identical to (pad ...) but it will pad with an arbitrary
       character (the 2nd argument).

       The first arguement must be an integer and the 2nd argument must be
       a single character or nothing will be returned. Other elements
       should be scalars.

   (column N LIST0 LIST1 ...)
       This returns a list of the Nth element of each of the listrefs. All
       arguments (except for the first) must be listrefs.

   (reverse ELE0 ELE1 ...)
       This returns the reverse of the list.

       All element types are allowed.

   (rotate N ELE0 ELE1 ...)
       This rotates the list of element N times. If N is positive, a single
       rotation is to remove the first element and put it on the end. If N
       is negative, a single rotation is to remove the last element and
       move it to the first.

       N must be an integer or nothing is returned. All element types are
       allowed for the list.

   (delete VAL ELE0 ELE1 ...)
       This removes all occurences of VAL from the list.

       VAL must be a scalar or nothing is returned. All other elements
       should be scalars.

   (clear ELE0 ELE1 ...)
       This clears all elements from the list and returns an empty list.

   (append STRING ELE0 ELE1 ...), (prepend STRING ELE0 ELE1 ...)
       These append or prepend a string to all elements in the list.

       The first element must be a scalar. All others should be scalars.

   (splice LIST N LEN [ELE0 ELE1 ...])
       This deletes LEN elements from LIST starting at element N and
       inserts the ELE elements in their place.

       LIST must be a list reference, N and LEN must be integers (LEN must
       be zero or positive). The remaining elements can be any type.

   (slice N LEN ELE0 ELE1 ...)
       This returns the slice of the list of elements starting with the Nth
       element and including LEN number of elements.

       N and LEN must be integers (LEN must be zero or positive). The
       remaining elements can be any type.

   (fill LIST N LEN VAL)
       This sets elements in LIST. The first argument is required, and must
       be a list reference. All other arguments are optional. Elements are
       numbered 0 to M or -(M+1) to -1. It is valid to refer to elements
       with an index greater than M (these are elements which will be added
       on to the right of the list), or less than -(M+1) (these are
       elements which will be added to the left.

       If N is given, it must be an integer. This is the index of the first
       element of the list to change.

       If LEN is given, it must be an integer. This is the number of
       elements to change starting at the Nth element and moving right. If
       it is negative, it is the number of elements to change starting with
       the Nth element and moving left. If LEN is zero,the list is
       unmodified.

       If VAL is set, all elements to be changed will be set to it.
       Otherwise, they will be set to "".

       The elements to be set depend on N and LEN (and M). The following
       table describes the changes for cases where LEN is not given. L
       refers to an index to the left of the list, R refers to an index to
       the right of the list, and C refers to an index in the list.

         N
         ===

         A   If both N and LEN are omitted, the entire list is
             filled with "".

         L   This adds blank elements to the left of the list
             out to (and including) the Lth element. Existing
             elements are unmodified.

         C   This sets from Cth element to the end of the list
             to "".

         R   This adds blank elements to the right of the list
             out to (and including) the Rth element. Existing
             elements are unmodified.

       For cases where LEN is given, N and LEN explicitly define the start
       and stop elements to modify. Either or both elements can be to the
       left of the list or to the right of the list.

       All elements in the (N,LEN) range are set to the value. If LEN goes
       past the end of the list, additional elements are added and set to
       that value. If N points to elements before the list, additional
       elements are added to the left.

       One possible confusion is when the operation is used to fill
       elements which are outside of the list entirely. For example if LIST
       contains:

         (a a a)

       and N is 4, LEN is 2, VAL is b, the resulting list is:

         (a a a "" b b)

       (so an empty element was added to get the list out to the portion
       that was being set).

   (difference LIST0 LIST1), (d_difference LIST0 LIST1)
       These take two lists and removes all elements in the second list
       from the first (and return the new list). The difference between the
       two is how duplicate entries are handled. In the first call, all
       duplicates are removed. In the second call, only one instance per
       element in the second list is removed.

         (difference [list a a b c] [list a]) => (b c)
         (d_difference [list a a b c] [list a]) => (a b c)

   (intersection LIST0 LIST1), (d_intersection LIST0 LIST1)
       This takes two lists and finds the intersection of the two. The
       intersection are the elements that are in both lists. In the first
       call, duplicates are ignored returning only a single instance of the
       intersection. In the second call, duplicates may be included in the
       intersection.

         (intersection [list a a b c] [list a a a b]) => (a b)
         (d_intersection [list a a b c] [list a a a b]) => (a a b)

   (symdiff LIST0 LIST1), (d_symdiff LIST0 LIST1)
       This takes the symmetric difference between two lists. The symmetric
       difference are elements that are in either list but not both. Again,
       duplicates are allowed in the second call.

         (symdiff [list a a b c] [list a a a b]) => (c)
         (d_symdiff [list a a b c] [list a a a b]) => (a c)

   The following variable operations are known:

   (getvar VAR)
       This returns the value of a variable named VAR. VAR must be a valid
       variable name or nothing is returned.

   (setvar VAR VAL)
       This sets the variable VAR to the given value (which may be a list
       or a scalar).

       Returns VAL.

   (default VAR VAL)
       This sets the values of VAR to VAL unless VAR already has a value.

       Returns the value of VAR.

   (unsetvar VAR)
       Removes VAR from the defined variables.

       Returns nothing.

   (shiftvar VAR), (popvar VAR)
       These shift or pop a value from the variable. Nothing is returned if
       the operation is not valid. Otherwise, the shifted/popped value is
       returned.

   (unshiftvar VAR VAL), (pushvar VAR VAL)
       These add a new element to the start or end of the given variable.
       If the variable refers to a scalar, it will be converted to a list.

       Nothing is returned.

EXAMPLES
   Reading a config file
       A simple config file might contain a two types of lines. The first
       type would be lines which actually set a config variable to a value:

         Var = Val

       and the second type would be lines which use this module to set more
       complex values:

         Var : ( ... )

       You might read the file, one line at a time, in the following way:

         use List::Parseable;
         $lp     = new List::Parseable;
         %CONFIG = ();

         @lines  = ...;        # @lines contains the lines from the config file

         foreach $line (@lines) {
           if      ($line =~ /^\s*(\S+)\s*=\s*(.*?)\s*$/) {
              set_value($1,$2);
           } elsif ($line =~ /^\s*(\S+)\s*:\s*(.*?)\s*$/) {
              parse_value($1,$2);
           }
         }

         # This stores a value in a variable. The value is stored in both
         # a global config hash and in the List::Parseable object so that
         # the config values can be used in setting complex values.
         #
         sub set_value {
            my($var,$val) = @_;

            $::CONFIG{$var} = $val;
            $lp->vars($var,$val);
         }

         # Set a complex variable using List::Parseable.
         #
         sub parse_value {
            my($var,$str) = @_;
            $lp->string("curr",$str);
            my ($val) = $lp->eval("curr");
            set_value($var,$val);
         }

   Setting a complex value
       If you have a config file with three values: ValA, ValB, and Ave,
       and you want Ave to be the average of ValA and ValB, but you don't
       want to build this into the program that reads the data, you could
       have the following (using the program in the example for reading a
       config file):

         ValA = 7
         ValB = 9
         Ave  : ( / ( + (getvar ValA) (getvar ValB) ) 2 )

   Supplying a missing value
       If you have a config file and you want to provide defaults for
       missing values, you can do the following:

         ValA = suppliedA
         ValA : (default ValA defaultA)
         ValB : (default ValB defaultB)

       This will result in the ValA being 'suppliedA' and ValB being
       'defaultB'.

BACKWARDS INCOMPATABILITIES
   1.01 no longer uses < as list delimiters>
       In order to simplify the use of the <, <=, >, and >= operators, the
       <> symbols will no longer be used as list delimiters.

BUGS AND QUESTIONS
   If you find a bug in this module, please send it directly to me (see the
   AUTHOR section below). Alternately, you can submit it on CPAN. This can
   be done at the following URL:

      http://rt.cpan.org/Public/Dist/Display.html?Name=List-Parseable

   Please do not use other means to report bugs (such as usenet newsgroups,
   or forums for a specific OS or linux distribution) as it is impossible
   for me to keep up with all of them.

   When filing a bug report, please include the following information:

   *   The version of the module you are using. You can get this by using
       the script:

               use List::Parseable;
               $obj = new List::Parseable;
               print $obj->version(),"\n";

   *   The output from "perl -V"

   If you have a problem using the module that perhaps isn't a bug (can't
   figure out the syntax, etc.), you're in the right place. Go right back
   to the top of this manual and start reading. If this still doesn't
   answer your question, mail me directly.

KNOWN PROBLEMS
   None at this point.

LICENSE
   This script is free software; you can redistribute it and/or modify it
   under the same terms as Perl itself.

AUTHOR
   Sullivan Beck ([email protected])