ctkDecTab

        Parse, generate and execute decision tables (decTab).

Syntax

Load the table declaration
        use ctkDecTab 1.05;
        my @decl = ctkDecTab::_load(<file name>);
Generate and execute code snippet
        if (ctkDecTab::parseAndBuildTable(@decl));
                if ($dt = ctkDecTab::buildSnippet()) {
                        eval "$dt ;".'xTable();';
                        die "Could not gen or exec decTab, $@" if ($@);
                }
        }
Generate and execute code block
        if (ctkDecTab::parseAndBuildTable(@decl));
                if ($dt = ctkDecTab::buildBlock()) {
                        eval $dt;
                        die "Could not gen decTab, $@" if ($@);
                } else { die "could not exec decTab"}
        }
Generate and execute package, i.e. package xmain
        if (ctkDecTab::parseAndBuildTable(@decl));
                if ($dt = ctkDecTab::buildPackage('xmain')
                        eval "$dt";
                        die "Could not gen decTab, $@" if ($@);
                        xmain::xTable();
                } else { die "could not exec decTab"}
        }
Generate package, save it to file and later on execute it
        unless (-f "xmain.pl") {
                my @decl = ctkParserDT::_load('xmain');
                if (ctkDecTab::parseAndBuildTable(@decl)) {
                        $dt = ctkDecTab::save('xmain');
                } else { die "could not exec decTab"}
        }
        ## somewhere in the script ...
        require "xmain.pl";
        while (<any loop-conditions>) {
                ## do something ...
                xmain::xTable();
        }

Description

        The goal of the package is to convert the declaration of
        a decision table into executable perl code.
        Thus, a decision table consists of
                - a declaration,
                - a piece of generated code which may be
                        - a package
                        - an anonimous block
                        - a snippet of code
        The declaration may look like this
                condition A   | 1  1  0  0
                condition B   | 1  0  1  0
                --------------+-----------
                action X      | x  x  -  -
                action Y      | x  -  x  -
        The declaration defines the conditions, the actions and their relationships.
        A defined set of actions are executed when the execution of all conditions
        yields a specific and defined result (state).
        That means there are as many different states as combinations of condition's results.
        Additionally, actions may be independent of specific conditions.
        Thus, the result of a condition can be discarded for specific states.
        That means, the result of a condition may get one of these values
        true, false or irrelevant.
        For instance, 3 conditions yield 9 possible distinct states which may lead
        to 9 different set of actions.
        (See the description of the method 'save' for an example.)
        Conditions and actions are perl statements.
        Conditions consist of Perl expressions which must return
        a boolean value.
        Actions may be any Perl expression, they are typically calls
        to a function (subroutine).
        It is the responsibility of the programmer to make sure that
        these statement can access the data in a proper way.
        The generated code consists of
                - the set of conditions, generated as closures,
                - the set of actions, also generated as closures and
                - the execution method xState. This method first executes
                  all conditions determinating the actual state and
                  then executes the actions defined for the actual state.
        The generated code can be saved into a module,
        which get loaded later on at run time by means of 'require' or 'use' ,
        or immediately executed by means of eval.
        Generated code snippet or anonimous block usually
        execute (eval) in the same package where are the status variables .
        Thus, conditions and actions may directly access these variables.
        By contrast, when the generated code is a package, problems may
        arise accessing variables of other packages and/or namespaces.
        It is the responsibility of the programmer to make these variables
        accessable in the conditions or actions.
        Unlike state machines, decision tables work at a specific time and
        are based on the specific state of the accessed variables.
        Therefore, these variables should not change while the code of the conditions
        are executed. On the other hand, once the state has been computed, the actions can update
        those variable.
        When several actions have to be executed for a specific state, then they are dispatched in the same
        order as they are defined in the decision table.
EBNF
        table      ::= (conditions) ('-') (actions) ('-')
        conditions ::= condition '¦' (values) nl
        condition  ::= (<Perl boolean expressions>)
        values     ::= 'Y' | '1' | 'N' | '0' | '-'
        actions    ::= method '¦' (indicators) nl
        method     ::= (<perl statement>)
        indicators ::= 'X' | '-'
        nl         ::= '\n'

Legend:

        ::=        operator 'consists of'
        |          OR operator
        space      AND operator
        word       indicate uniquely an item of the EBNF declaration
        'x'        string constant
        < >        explanatory text, acting as a placeholder for an item
        ()         1 - N list of given item

Programming notes

Class data member
        $state          state while parsing
        @conditions     list of the declared conditions
        @actions        list of the declared actions
        @decisionTable  content of the decision table
        @DT             generated code as saved to target
Data member
        None
Properties
        debug
Constructor
        Send message  _load to load an external declaration.
        Use parse(<array>) to work with a declaration saved
        in a script variable.
Destructor
        Send message _clearClassData.
Method's list
        _clear
        _clearClassData
        _load
        _parseConditionOrAction
        buildBlock
        buildPackage
        buildSnippet
        buildTable
        getDT
        parse
        parseAndBuildTable
        prepareActions
        prepareDecisions
        save

Maintenance

        Author: Marco
        date:   19.09.2008
        History
                        19.09.2008 first draft
                        24.09.2008 version 1.05

Methods

_clear

        Clear the content of the  DT class member.

_clearClassData

        Clear the content of all class members.

getDT

        Return the content of the class data member DT
        as array or string depending on the context.

_load

        Load the given definition into memory and
        return it as array or string depending on the context.
        If no file name is given, STDIN shall be used.

buildPackage

        Generate the Perl package containing the
        generated table and code previously saved into class member @decisionTable.
        Issue exception "Cannot gen an empty table" if class member
        @decisionTable is empty.
        Return the generated code either as an array of lines or as a string of
        concatenated lines depending on the context.

buildBlock

        Generate the Perl block containing the
        generated table and code previously saved into class member @decisionTable
        and the message xTable().
        Issue exception "Cannot gen an empty table" if class member
        @decisionTable is empty.
        Return the generated code either as an array of lines or as a string of
        concatenated lines depending on the context.

buildSnippet

        Generate the Perl code containing the
        generated table and code previously saved into class member @decisionTable.
        Issue exception "Cannot gen an empty table" if class member
        @decisionTable is empty.
        Return the generated code either as an array of lines or as a string of
        concatenated lines depending on the context.

save

        Build code and either save it to disk or
        put it into STDOUT.
        Thereby, apply the following decision table:
                module name given     | y  y  y  n  n  n
                package name given    | y  y  n  y  y  n
                package name is empty | n  y  -  n  y  -
                ----------------------+------------------
                gen package           | x  x  x  x  -  -
                gen package main      | -  x  -  -  x  -
                gen block             | -  -  -  -  -  x
                write to file         | x  x  x  -  -  -
                write to STDOUT       | -  -  -  x  x  x
                ----------------------+------------------
        Return the number of written lines.

_parseConditionOrAction

        Parse the given declaration's line and return
        depending on the context  the list of the tokens
        or their number.

prepareDecisions

        Build up and save the conditions into the
        class data member @decisionTable.
        Return the number of conditions.

prepareActions

        Build up and save the actions into the
        class data member @decisionTable.
        Return the number of conditions.

buildTable

        Build up the method xTable using the class data members @conditions and @actions
        and save the code into the class data member @decisionTable.
        Return the number of processed states.

parse

        Parse the declaration and build up the class data
        members decision and actions.
        Return the number of declared actions.

parseAndBuildTable

        Parse the declaration and build up the method xTable,
        save the code into the class data member @decisiontable and
        return its content depending on the context as an array of lines
        or as a string.
        This method takes the same arguments as message ctkDecTab::parse does.
        Arguments are passed 'as is' to the method ctkDecTab::parse .
        In array context the returned array is identical to the class variable @decisiontable
        In scalar context the returned string is the
        concatenation of the class variable @decisiontable

Back to index