Full support for arrays => min, max and avg funcs accept array argument. Also array function is defined which return arguments as array. Square bracket arrays are also supported. (#108)
valid expression -> "max([1,2,3])" valid expression -> "max(array(1,2,3))" valid expression -> "max($ages_arr)" valid expression -> "max(ages_arr())"
This commit is contained in:
parent
2874b11341
commit
5d6b4a5dfd
4 changed files with 43 additions and 7 deletions
20
README.md
20
README.md
|
@ -40,6 +40,7 @@ Default functions:
|
|||
* arcctg (arccot, arccotan)
|
||||
* arcsec
|
||||
* arccsc (arccosec)
|
||||
* array
|
||||
* asin (arcsin)
|
||||
* atan (atn, arctan, arctg)
|
||||
* atan2
|
||||
|
@ -84,7 +85,10 @@ Add custom function to executor:
|
|||
```php
|
||||
$executor->addFunction('abs', function($arg) {return abs($arg);});
|
||||
```
|
||||
Function default parameters are not supported at this time.
|
||||
Function default parameters (optional parameters) are also supported.
|
||||
```php
|
||||
$executor->addFunction('round', function($num, int $precision = 0) {return round($num, $precision);});
|
||||
```
|
||||
|
||||
## Operators:
|
||||
Default operators: `+ - * / ^`
|
||||
|
@ -139,12 +143,20 @@ $executor->setVar('var1', 0.15)->setVar('var2', 0.22);
|
|||
echo $executor->execute("$var1 + var2");
|
||||
```
|
||||
|
||||
By default, variables must be scalar values (int, float, bool or string). If you would like to support another type, use **setVarValidationHandler**
|
||||
Arrays are also supported (as variables, as func params or can be returned in user defined funcs):
|
||||
```php
|
||||
$executor->setVar('monthly_salaries', [1800, 1900, 1200, 1600]);
|
||||
|
||||
echo $executor->execute("avg(monthly_salaries) * min([1.1, 1.3])");
|
||||
```
|
||||
|
||||
|
||||
By default, variables must be scalar values (int, float, bool or string) or array. If you would like to support another type, use **setVarValidationHandler**
|
||||
|
||||
```php
|
||||
$executor->setVarValidationHandler(function (string $name, $variable) {
|
||||
// allow all scalars and null
|
||||
if (is_scalar($variable) || $variable === null) {
|
||||
// allow all scalars, array and null
|
||||
if (is_scalar($variable) || is_array($variable) || $variable === null) {
|
||||
return;
|
||||
}
|
||||
// Allow variables of type DateTime, but not others
|
||||
|
|
|
@ -76,6 +76,13 @@ class Tokenizer
|
|||
|
||||
continue 2;
|
||||
|
||||
case '[' === $ch:
|
||||
$this->tokens[] = new Token(Token::Function, 'array');
|
||||
$this->allowNegative = true;
|
||||
$this->tokens[] = new Token(Token::LeftParenthesis, '');
|
||||
|
||||
continue 2;
|
||||
|
||||
case ' ' == $ch || "\n" == $ch || "\r" == $ch || "\t" == $ch:
|
||||
$this->tokens[] = new Token(Token::Space, '');
|
||||
|
||||
|
@ -140,7 +147,7 @@ class Tokenizer
|
|||
|
||||
break;
|
||||
|
||||
case $this->isRP($ch):
|
||||
case $this->isRP($ch) || ']' === $ch :
|
||||
$this->emptyNumberBufferAsLiteral();
|
||||
$this->emptyStrBufferAsVariable();
|
||||
$this->allowNegative = false;
|
||||
|
@ -196,8 +203,8 @@ class Tokenizer
|
|||
}
|
||||
|
||||
/**
|
||||
* @throws UnknownOperatorException
|
||||
* @throws IncorrectBracketsException
|
||||
* @throws UnknownOperatorException
|
||||
* @return Token[] Array of tokens in revers polish notation
|
||||
*/
|
||||
public function buildReversePolishNotation() : array
|
||||
|
|
|
@ -469,7 +469,8 @@ class MathExecutor
|
|||
'tan' => static fn($arg) => \tan($arg),
|
||||
'tanh' => static fn($arg) => \tanh($arg),
|
||||
'tn' => static fn($arg) => \tan($arg),
|
||||
'tg' => static fn($arg) => \tan($arg)
|
||||
'tg' => static fn($arg) => \tan($arg),
|
||||
'array' => static fn(...$args) => [...$args]
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -305,6 +305,22 @@ class MathTest extends TestCase
|
|||
$this->assertEquals(100, $calculator->execute('10 ^ 2'));
|
||||
}
|
||||
|
||||
public function testArrays() : void
|
||||
{
|
||||
$calculator = new MathExecutor();
|
||||
$this->assertEquals([1, 5, 2], $calculator->execute('array(1, 5, 2)'));
|
||||
$this->assertEquals([1, 5, 2], $calculator->execute('[1, 5, 2]'));
|
||||
$this->assertEquals(\max([1, 5, 2]), $calculator->execute('max([1, 5, 2])'));
|
||||
$this->assertEquals(\max([1, 5, 2]), $calculator->execute('max(array(1, 5, 2))'));
|
||||
$calculator->addFunction('arr_with_max_elements', static function($arg1, ...$args) {
|
||||
$args = \is_array($arg1) ? $arg1 : [$arg1, ...$args];
|
||||
\usort($args, static fn($arr1, $arr2) => \count($arr2) <=> \count($arr1));
|
||||
|
||||
return $args[0];
|
||||
});
|
||||
$this->assertEquals([3, 3, 3], $calculator->execute('arr_with_max_elements([[1],array(2,2),[3,3,3]])'));
|
||||
}
|
||||
|
||||
public function testFunctionParameterOrder() : void
|
||||
{
|
||||
$calculator = new MathExecutor();
|
||||
|
|
Loading…
Reference in a new issue