Parse, generate and execute decision tables (decTab).
use ctkDecTab 1.05;
my @decl = ctkDecTab::_load(<file name>);
if (ctkDecTab::parseAndBuildTable(@decl));
if ($dt = ctkDecTab::buildSnippet()) {
eval "$dt ;".'xTable();';
die "Could not gen or exec decTab, $@" if ($@);
}
}
if (ctkDecTab::parseAndBuildTable(@decl));
if ($dt = ctkDecTab::buildBlock()) {
eval $dt;
die "Could not gen decTab, $@" if ($@);
} else { die "could not exec decTab"}
}
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"}
}
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();
}
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.
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
$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
None
debug
Send message _load to load an external declaration.
Use parse(<array>) to work with a declaration saved
in a script variable.
Send message _clearClassData.
_clear
_clearClassData
_load
_parseConditionOrAction
buildBlock
buildPackage
buildSnippet
buildTable
getDT
parse
parseAndBuildTable
prepareActions
prepareDecisions
save
Author: Marco
date: 19.09.2008
History
19.09.2008 first draft
24.09.2008 version 1.05
Clear the content of the DT class member.
Clear the content of all class members.
Return the content of the class data member DT
as array or string depending on the context.
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.
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.
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.
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.
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.
Parse the given declaration's line and return
depending on the context the list of the tokens
or their number.
Build up and save the conditions into the
class data member @decisionTable.
Return the number of conditions.
Build up and save the actions into the
class data member @decisionTable.
Return the number of conditions.
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 the declaration and build up the class data
members decision and actions.
Return the number of declared actions.
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 |