At the moment I have some PHP which sets a single variable based on the value of other independent variables in a linear format, like so:
$result = 0;
if ($var1 == 'X') {
$result += 10;
}
if ($var2 < 10) {
$result += 15;
}
elseif ($var2 > 50) {
$result -= 50;
}
// more of the same
However, I'd like to be able to express these rules in a less programming-like way, mainly so that someone who doesn't know how to program can add/edit rules, and also because I might want to use the same rules in a Python or Perl script, without having to maintain copies in multiple languages. I could write my own simple language (for want of a better word) and parser, but I'd prefer to use an existing solution as that saves work and increases the likelihood that other people will know how to write rules in it.
Is there a sensible/obvious choice for this sort of task?
I don't think you need a language/parser for this. You could create an expression builder (similar to how one creates email message filter rules) and store the results in a database. This will also allow other languages to access the stored rules.
Users would add comparisons until satisfied, then enter the associated assignment rule.
Design a little pseudo-language and convert it to PHP code.
$var1 == 'X': +10
$var2 < 10: +15
$var2 > 50: -50
Now you can use the PHP Tokenizer to parse this and convert it to real PHP code. Then you should cache the generated code and include it as a PHP file.
This is a really quick and dirty implementation using my own TokenStream class (but you could easily port that to the native tokenizer):
<?php
$code =<<<'EOC'
$var1 == 'X': +10
$var2 < 10: +15
$var2 > 50: -50
EOC;
require '../tokenstream/src/TokenStream.php';
$tokenStream = new TokenStream('<?php ' . $code);
$code = '';
foreach ($tokenStream as $i => $token) {
if ($token->is(T_OPEN_TAG)) {
$code .= '<?php $result = 0;' . PHP_EOL . 'if (';
}
elseif ($token->is(T_WHITESPACE) && preg_match("[\r\n]", $token->content)) {
$code .= ';' . $token . 'if (';
}
elseif ($token->is(T_COLON)) {
$code .= ') $result += ';
}
else {
$code .= $token;
}
}
$code .= ';';
echo '<pre>', htmlspecialchars($code), '</pre>';
It is really quick and dirty. You could execute arbitrary code. For a better implementation you would need to implement a state machine and I hadn't got the time right now ;)
Script output:
<?php $result = 0;
if ($var1 == 'X') $result += +10;
if ($var2 < 10) $result += +15;
if ($var2 > 50) $result += -50;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With