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:
Fatih Kızmaz 2022-05-17 00:57:37 +03:00 committed by GitHub
parent 2874b11341
commit 5d6b4a5dfd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 7 deletions

View file

@ -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

View file

@ -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

View file

@ -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]
];
}

View file

@ -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();