diff --git a/README.md b/README.md index b86f9c6..81d9475 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MathExecutor [![Stories in Ready](https://badge.waffle.io/NeonXP/MathExecutor.png?label=ready&title=Ready)](https://waffle.io/NeonXP/MathExecutor) [![Build Status](https://travis-ci.org/NeonXP/MathExecutor.png?branch=master)](https://travis-ci.org/NeonXP/MathExecutor) -A simple math expressions calculator +# A simple and extensible math expressions calculator ## Features: * Built in support for +, -, *, / and power (^) operators plus () @@ -11,7 +11,7 @@ A simple math expressions calculator * Exceptions on divide by zero, or treat as zero * Unary Minus (e.g. -3) * Pi ($pi) and Euler's number ($e) support to 11 decimal places -* Easily extendable +* Easily extensible ## Install via Composer: ``` @@ -41,10 +41,9 @@ Default functions: Add custom function to executor: ```php -$executor->addFunction('abs', function($arg) { - return abs($arg); -}, 1); +$executor->addFunction('abs', function($arg) {return abs($arg);}); ``` +Function default parameters are not supported at this time. ## Operators: Default operators: `+ - * / ^` diff --git a/src/NXP/Classes/Calculator.php b/src/NXP/Classes/Calculator.php index 1ceac84..62dbc17 100644 --- a/src/NXP/Classes/Calculator.php +++ b/src/NXP/Classes/Calculator.php @@ -38,22 +38,18 @@ public function calculate($tokens, $variables) foreach ($tokens as $token) { if ($token instanceof TokenNumber) { array_push($stack, $token); - } - if ($token instanceof TokenStringDoubleQuoted) { + } else if ($token instanceof TokenStringDoubleQuoted) { array_push($stack, $token); - } - if ($token instanceof TokenStringSingleQuoted) { + } else if ($token instanceof TokenStringSingleQuoted) { array_push($stack, $token); - } - if ($token instanceof TokenVariable) { + } else if ($token instanceof TokenVariable) { $variable = $token->getValue(); if (!array_key_exists($variable, $variables)) { throw new UnknownVariableException($variable); } $value = $variables[$variable]; array_push($stack, new TokenNumber($value)); - } - if ($token instanceof InterfaceOperator || $token instanceof TokenFunction) { + } else if ($token instanceof InterfaceOperator || $token instanceof TokenFunction) { array_push($stack, $token->execute($stack)); } } diff --git a/src/NXP/Classes/Token/TokenFunction.php b/src/NXP/Classes/Token/TokenFunction.php index b2866c3..04eae30 100644 --- a/src/NXP/Classes/Token/TokenFunction.php +++ b/src/NXP/Classes/Token/TokenFunction.php @@ -32,9 +32,9 @@ public function execute(&$stack) $args = []; list($places, $function) = $this->value; for ($i = 0; $i < $places; $i++) { - array_push($args, array_pop($stack)->getValue()); + $args[] = array_pop($stack)->getValue(); } - $result = call_user_func_array($function, $args); + $result = call_user_func_array($function, array_reverse($args)); return new TokenNumber($result); } diff --git a/src/NXP/MathExecutor.php b/src/NXP/MathExecutor.php index 29c6a64..6325d35 100644 --- a/src/NXP/MathExecutor.php +++ b/src/NXP/MathExecutor.php @@ -174,7 +174,7 @@ public function getOperators() * @return MathExecutor * @throws \ReflectionException */ - public function addFunction($name, $function = null, $places = 1) + public function addFunction($name, $function = null, $places = null) { $this->tokenFactory->addFunction($name, $function, $places); diff --git a/tests/MathTest.php b/tests/MathTest.php index 55e0799..8eb7827 100644 --- a/tests/MathTest.php +++ b/tests/MathTest.php @@ -32,7 +32,7 @@ public function testCalculating($expression) /** @var float $phpResult */ eval('$phpResult = ' . $expression . ';'); - $this->assertEquals($calculator->execute($expression), $phpResult, "Expression was: ${expression}"); + $this->assertEquals($phpResult, $calculator->execute($expression), "Expression was: ${expression}"); } /** @@ -117,7 +117,7 @@ public function testIncorrectExpressionException() public function testZeroDivision() { $calculator = new MathExecutor(); - $this->assertEquals($calculator->execute('10 / 0'), 0); + $this->assertEquals(0, $calculator->execute('10 / 0')); } public function testZeroDivisionException() @@ -131,19 +131,25 @@ public function testZeroDivisionException() public function testExponentiation() { $calculator = new MathExecutor(); - $this->assertEquals($calculator->execute('10 ^ 2'), 100); + $this->assertEquals(100, $calculator->execute('10 ^ 2')); } + public function testFunctionParameterOrder() + { + $calculator = new MathExecutor(); + + $calculator->addFunction('concat', function ($arg1, $arg2) {return $arg1.$arg2;}); + $this->assertEquals('testing', $calculator->execute('concat("test","ing")')); + $this->assertEquals('testing', $calculator->execute("concat('test','ing')")); + } + public function testFunction() { $calculator = new MathExecutor(); - - $calculator->addFunction('round', function ($arg) { - return round($arg); - }, 1); + $calculator->addFunction('round', function ($arg) {return round($arg);}); /** @var float $phpResult */ eval('$phpResult = round(100/30);'); - $this->assertEquals($calculator->execute('round(100/30)'), $phpResult); + $this->assertEquals($phpResult, $calculator->execute('round(100/30)')); } public function testQuotes() @@ -151,9 +157,9 @@ public function testQuotes() $calculator = new MathExecutor(); $testString = "some, long. arg; with: different-separators!"; $calculator->addFunction('test', function ($arg) use ($testString) { - $this->assertEquals($arg, $testString); - return 0; - }, 1); + $this->assertEquals($testString, $arg); + return 0;} + ); $calculator->execute('test("' . $testString . '")'); // single quotes $calculator->execute("test('" . $testString . "')"); // double quotes }