aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/NXP/Classes/Calculator.php2
-rw-r--r--src/NXP/Classes/CustomFunction.php5
-rw-r--r--src/NXP/Classes/Operator.php1
-rw-r--r--src/NXP/Classes/Tokenizer.php16
-rw-r--r--src/NXP/Exception/IncorrectNumberOfFunctionParametersException.php16
-rw-r--r--tests/MathTest.php68
6 files changed, 97 insertions, 11 deletions
diff --git a/src/NXP/Classes/Calculator.php b/src/NXP/Classes/Calculator.php
index 94c6933..bcb4b4e 100644
--- a/src/NXP/Classes/Calculator.php
+++ b/src/NXP/Classes/Calculator.php
@@ -77,7 +77,7 @@ class Calculator
}
$result = array_pop($stack);
if ($result === null || !empty($stack)) {
- throw new IncorrectExpressionException();
+ throw new IncorrectExpressionException('Stack must be empty');
}
return $result->value;
}
diff --git a/src/NXP/Classes/CustomFunction.php b/src/NXP/Classes/CustomFunction.php
index 06e21ef..f127ad2 100644
--- a/src/NXP/Classes/CustomFunction.php
+++ b/src/NXP/Classes/CustomFunction.php
@@ -3,7 +3,7 @@
namespace NXP\Classes;
-use NXP\Exception\IncorrectExpressionException;
+use NXP\Exception\IncorrectNumberOfFunctionParametersException;
use ReflectionException;
use ReflectionFunction;
@@ -30,6 +30,7 @@ class CustomFunction
* @param callable $function
* @param int $places
* @throws ReflectionException
+ * @throws IncorrectNumberOfFunctionParametersException
*/
public function __construct(string $name, callable $function, ?int $places = null)
{
@@ -46,7 +47,7 @@ class CustomFunction
public function execute(array &$stack) : Token
{
if (count($stack) < $this->places) {
- throw new IncorrectExpressionException();
+ throw new IncorrectNumberOfFunctionParametersException($this->name);
}
$args = [];
for ($i = 0; $i < $this->places; $i++) {
diff --git a/src/NXP/Classes/Operator.php b/src/NXP/Classes/Operator.php
index 86df549..00485bc 100644
--- a/src/NXP/Classes/Operator.php
+++ b/src/NXP/Classes/Operator.php
@@ -46,7 +46,6 @@ class Operator
$this->isRightAssoc = $isRightAssoc;
$this->priority = $priority;
$this->function = $function;
- $this->function = $function;
$reflection = new ReflectionFunction($function);
$this->places = $reflection->getNumberOfParameters();
}
diff --git a/src/NXP/Classes/Tokenizer.php b/src/NXP/Classes/Tokenizer.php
index 6b14677..203724a 100644
--- a/src/NXP/Classes/Tokenizer.php
+++ b/src/NXP/Classes/Tokenizer.php
@@ -157,14 +157,16 @@ class Tokenizer
}
$this->emptyNumberBufferAsLiteral();
$this->emptyStrBufferAsVariable();
- if (count($this->tokens) > 0) {
- if ($this->tokens[count($this->tokens) - 1]->type === Token::Operator) {
- $this->tokens[count($this->tokens) - 1]->value .= $ch;
+ if ($ch != '$') {
+ if (count($this->tokens) > 0) {
+ if ($this->tokens[count($this->tokens) - 1]->type === Token::Operator) {
+ $this->tokens[count($this->tokens) - 1]->value .= $ch;
+ } else {
+ $this->tokens[] = new Token(Token::Operator, $ch);
+ }
} else {
$this->tokens[] = new Token(Token::Operator, $ch);
}
- } else {
- $this->tokens[] = new Token(Token::Operator, $ch);
}
$this->allowNegative = true;
}
@@ -251,12 +253,12 @@ class Tokenizer
break;
case Token::Operator:
if (!array_key_exists($token->value, $this->operators)) {
- throw new UnknownOperatorException();
+ throw new UnknownOperatorException($token->value);
}
$op1 = $this->operators[$token->value];
while ($stack->count() > 0 && $stack->top()->type === Token::Operator) {
if (!array_key_exists($stack->top()->value, $this->operators)) {
- throw new UnknownOperatorException();
+ throw new UnknownOperatorException($stack->top()->value);
}
$op2 = $this->operators[$stack->top()->value];
if ($op2->priority >= $op1->priority) {
diff --git a/src/NXP/Exception/IncorrectNumberOfFunctionParametersException.php b/src/NXP/Exception/IncorrectNumberOfFunctionParametersException.php
new file mode 100644
index 0000000..4c66bdf
--- /dev/null
+++ b/src/NXP/Exception/IncorrectNumberOfFunctionParametersException.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the MathExecutor package
+ *
+ * (c) Alexander Kiryukhin
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code
+ */
+
+namespace NXP\Exception;
+
+class IncorrectNumberOfFunctionParametersException extends MathExecutorException
+{
+}
diff --git a/tests/MathTest.php b/tests/MathTest.php
index 6108bd8..ee9c6bd 100644
--- a/tests/MathTest.php
+++ b/tests/MathTest.php
@@ -14,7 +14,9 @@ namespace NXP\Tests;
use Exception;
use NXP\Exception\DivisionByZeroException;
use NXP\Exception\IncorrectExpressionException;
+use NXP\Exception\IncorrectNumberOfFunctionParametersException;
use NXP\Exception\UnknownFunctionException;
+use NXP\Exception\UnknownVariableException;
use NXP\MathExecutor;
use PHPUnit\Framework\TestCase;
@@ -234,6 +236,18 @@ class MathTest extends TestCase
$calculator = new MathExecutor();
$this->expectException(DivisionByZeroException::class);
$calculator->execute('10 / 0');
+ $calculator->setVar('one', 1)->setVar('zero', 0);
+ $this->assertEquals(0.0, $calculator->execute('$one / $zero'));
+ }
+
+ public function testVariableIncorrectExpressionException()
+ {
+ $calculator = new MathExecutor();
+ $calculator->setVar('four', 4);
+ $this->assertEquals(4, $calculator->execute('$four'));
+ $this->expectException(IncorrectExpressionException::class);
+ $this->assertEquals(0.0, $calculator->execute('$'));
+ $this->assertEquals(0.0, $calculator->execute('$ + $four'));
}
public function testExponentiation()
@@ -289,6 +303,60 @@ class MathTest extends TestCase
$this->assertEquals(cos(2), $calculator->execute(
'if(cos(2), cos(2), 0)'
));
+ $trx_amount = 100000;
+ $calculator->setVar('trx_amount', $trx_amount);
+ $this->assertEquals($trx_amount, $calculator->execute('$trx_amount'));
+ $this->assertEquals($trx_amount * 0.03, $calculator->execute(
+ 'if($trx_amount < 40000, $trx_amount * 0.06, $trx_amount * 0.03)'
+ ));
+ $this->assertEquals($trx_amount * 0.03, $calculator->execute(
+ 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))'
+ ));
+ $trx_amount = 39000;
+ $calculator->setVar('trx_amount', $trx_amount);
+ $this->assertEquals($trx_amount * 0.06, $calculator->execute(
+ 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))'
+ ));
+ $trx_amount = 59000;
+ $calculator->setVar('trx_amount', $trx_amount);
+ $this->assertEquals($trx_amount * 0.05, $calculator->execute(
+ 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))'
+ ));
+ $this->expectException(IncorrectNumberOfFunctionParametersException::class);
+ $this->assertEquals(0.0, $calculator->execute(
+ 'if($trx_amount < 40000, $trx_amount * 0.06)'
+ ));
+ }
+
+ public function testVariables()
+ {
+ $calculator = new MathExecutor();
+ $this->assertEquals(3.14159265359, $calculator->execute('$pi'));
+ $this->assertEquals(2.71828182846, $calculator->execute('$e'));
+ $calculator->setVars([
+ 'trx_amount' => 100000,
+ 'ten' => 10,
+ 'nine' => 9,
+ 'eight' => 8,
+ 'seven' => 7,
+ 'six' => 6,
+ 'five' => 5,
+ 'four' => 4,
+ 'three' => 3,
+ 'two' => 2,
+ 'one' => 1,
+ 'zero' => 0,
+ ]);
+ $this->assertEquals(100000, $calculator->execute('$trx_amount'));
+ $this->assertEquals(10 - 9, $calculator->execute('$ten - $nine'));
+ $this->assertEquals(9 - 10, $calculator->execute('$nine - $ten'));
+ $this->assertEquals(10 + 9, $calculator->execute('$ten + $nine'));
+ $this->assertEquals(10 * 9, $calculator->execute('$ten * $nine'));
+ $this->assertEquals(10 / 9, $calculator->execute('$ten / $nine'));
+ $this->assertEquals(10 / (9 / 5), $calculator->execute('$ten / ($nine / $five)'));
+
+ $this->expectException(UnknownVariableException::class);
+ $this->assertEquals(0.0, $calculator->execute('$unsetVariable'));
}
public function testEvaluateFunctionParameters()