Support for unary positive expressions (#85)

* Support for unary positive operator
This commit is contained in:
Javier Marín 2021-03-05 01:42:01 +01:00 committed by GitHub
parent 17cc5b9dc4
commit d99491c1f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 23 deletions

View file

@ -150,11 +150,11 @@ class Tokenizer
$this->tokens[] = new Token(Token::ParamSeparator, ''); $this->tokens[] = new Token(Token::ParamSeparator, '');
break; break;
default: default:
// special case for unary minus // special case for unary operations
if ($ch == '-') { if ($ch == '-' || $ch == '+') {
if ($this->allowNegative) { if ($this->allowNegative) {
$this->allowNegative = false; $this->allowNegative = false;
$this->tokens[] = new Token(Token::Operator, '`'); $this->tokens[] = new Token(Token::Operator, $ch == '-' ? 'uNeg' : 'uPos');
continue 2; continue 2;
} }
// could be in exponent, in which case negative should be added to the numberBuffer // could be in exponent, in which case negative should be added to the numberBuffer

View file

@ -16,8 +16,8 @@ use NXP\Classes\CustomFunction;
use NXP\Classes\Operator; use NXP\Classes\Operator;
use NXP\Classes\Tokenizer; use NXP\Classes\Tokenizer;
use NXP\Exception\DivisionByZeroException; use NXP\Exception\DivisionByZeroException;
use NXP\Exception\UnknownVariableException;
use NXP\Exception\MathExecutorException; use NXP\Exception\MathExecutorException;
use NXP\Exception\UnknownVariableException;
use ReflectionException; use ReflectionException;
/** /**
@ -85,35 +85,42 @@ class MathExecutor
protected function defaultOperators() : array protected function defaultOperators() : array
{ {
return [ return [
'+' => [ '+' => [
function ($a, $b) { function ($a, $b) {
return $a + $b; return $a + $b;
}, },
170, 170,
false false
], ],
'-' => [ '-' => [
function ($a, $b) { function ($a, $b) {
return $a - $b; return $a - $b;
}, },
170, 170,
false false
], ],
'`' => [ // unary minus token 'uPos' => [ // unary positive token
function ($a) { function ($a) {
return 0 - $a; return $a;
}, },
200, 200,
false false
], ],
'*' => [ 'uNeg' => [ // unary minus token
function ($a) {
return 0 - $a;
},
200,
false
],
'*' => [
function ($a, $b) { function ($a, $b) {
return $a * $b; return $a * $b;
}, },
180, 180,
false false
], ],
'/' => [ '/' => [
function ($a, $b) { function ($a, $b) {
if ($b == 0) { if ($b == 0) {
throw new DivisionByZeroException(); throw new DivisionByZeroException();
@ -123,28 +130,28 @@ class MathExecutor
180, 180,
false false
], ],
'^' => [ '^' => [
function ($a, $b) { function ($a, $b) {
return pow($a, $b); return pow($a, $b);
}, },
220, 220,
true true
], ],
'&&' => [ '&&' => [
function ($a, $b) { function ($a, $b) {
return $a && $b; return $a && $b;
}, },
100, 100,
false false
], ],
'||' => [ '||' => [
function ($a, $b) { function ($a, $b) {
return $a || $b; return $a || $b;
}, },
90, 90,
false false
], ],
'==' => [ '==' => [
function ($a, $b) { function ($a, $b) {
if (is_string($a) || is_string($b)) { if (is_string($a) || is_string($b)) {
return strcmp($a, $b) == 0; return strcmp($a, $b) == 0;
@ -155,7 +162,7 @@ class MathExecutor
140, 140,
false false
], ],
'!=' => [ '!=' => [
function ($a, $b) { function ($a, $b) {
if (is_string($a) || is_string($b)) { if (is_string($a) || is_string($b)) {
return strcmp($a, $b) != 0; return strcmp($a, $b) != 0;
@ -166,28 +173,28 @@ class MathExecutor
140, 140,
false false
], ],
'>=' => [ '>=' => [
function ($a, $b) { function ($a, $b) {
return $a >= $b; return $a >= $b;
}, },
150, 150,
false false
], ],
'>' => [ '>' => [
function ($a, $b) { function ($a, $b) {
return $a > $b; return $a > $b;
}, },
150, 150,
false false
], ],
'<=' => [ '<=' => [
function ($a, $b) { function ($a, $b) {
return $a <= $b; return $a <= $b;
}, },
150, 150,
false false
], ],
'<' => [ '<' => [
function ($a, $b) { function ($a, $b) {
return $a < $b; return $a < $b;
}, },

View file

@ -252,6 +252,17 @@ class MathTest extends TestCase
$this->assertEquals(0, $calculator->execute('10 / 0')); $this->assertEquals(0, $calculator->execute('10 / 0'));
} }
public function testUnaryOperators()
{
$calculator = new MathExecutor();
$this->assertEquals(5, $calculator->execute('+5'));
$this->assertEquals(5, $calculator->execute('+(3+2)'));
$this->assertEquals(-5, $calculator->execute('-5'));
$this->assertEquals(5, $calculator->execute('-(-5)'));
$this->assertEquals(-5, $calculator->execute('+(-5)'));
$this->assertEquals(-5, $calculator->execute('-(3+2)'));
}
public function testZeroDivisionException() public function testZeroDivisionException()
{ {
$calculator = new MathExecutor(); $calculator = new MathExecutor();