Skip to content

Commit

Permalink
Variable fixes (#67)
Browse files Browse the repository at this point in the history
* Reproduce if throws UnknownOperatorException

* Fix variable detection

* Adding IncorrectNumberOfFunctionParametersException

* Removing tabs

* Better exception message text
  • Loading branch information
phpfui authored Jun 4, 2020
1 parent ea898d7 commit aa8ffe1
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/NXP/Classes/Calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function calculate(array $tokens, array $variables)
}
$result = array_pop($stack);
if ($result === null || !empty($stack)) {
throw new IncorrectExpressionException();
throw new IncorrectExpressionException('Stack must be empty');
}
return $result->value;
}
Expand Down
5 changes: 3 additions & 2 deletions src/NXP/Classes/CustomFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace NXP\Classes;

use NXP\Exception\IncorrectExpressionException;
use NXP\Exception\IncorrectNumberOfFunctionParametersException;
use ReflectionException;
use ReflectionFunction;

Expand All @@ -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)
{
Expand All @@ -46,7 +47,7 @@ public function __construct(string $name, callable $function, ?int $places = nul
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++) {
Expand Down
1 change: 0 additions & 1 deletion src/NXP/Classes/Operator.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public function __construct(string $operator, bool $isRightAssoc, int $priority,
$this->isRightAssoc = $isRightAssoc;
$this->priority = $priority;
$this->function = $function;
$this->function = $function;
$reflection = new ReflectionFunction($function);
$this->places = $reflection->getNumberOfParameters();
}
Expand Down
16 changes: 9 additions & 7 deletions src/NXP/Classes/Tokenizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,16 @@ public function tokenize() : self
}
$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;
}
Expand Down Expand Up @@ -251,12 +253,12 @@ public function buildReversePolishNotation() : array
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) {
Expand Down
16 changes: 16 additions & 0 deletions src/NXP/Exception/IncorrectNumberOfFunctionParametersException.php
Original file line number Diff line number Diff line change
@@ -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
{
}
68 changes: 68 additions & 0 deletions tests/MathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
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;

Expand Down Expand Up @@ -234,6 +236,18 @@ public function testZeroDivisionException()
$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()
Expand Down Expand Up @@ -289,6 +303,60 @@ public function testFunctionIf()
$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()
Expand Down

0 comments on commit aa8ffe1

Please sign in to comment.