Skip to content

Commit

Permalink
Subtraction fix (#46)
Browse files Browse the repository at this point in the history
* Updated unit tests
* Fixed docs
* Better unary minus support
  • Loading branch information
phpfui authored Aug 16, 2019
1 parent 36b252b commit ce50015
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
vendor/
.idea/
composer.lock
composer.lock
.phpunit.result.cache
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ $executor->addFunction('abs', function($arg) {return abs($arg);});
```
Function default parameters are not supported at this time.

Default parameters are not currently supported.

## Operators:
Default operators: `+ - * / ^`

Expand Down Expand Up @@ -112,7 +114,7 @@ Default variables:

```
$pi = 3.14159265359
$e = 2.71828182846
$e = 2.71828182846
```

You can add your own variables to executor:
Expand All @@ -138,7 +140,7 @@ try {
```

## Unary Minus Operator:
Negative numbers are supported via the unary minus operator, but need to have a space before the minus sign. `-1+ -3` is legal, while `-1+-3` will produce an error due to the way the parser works. Positive numbers are not explicitly supported as unsigned numbers are assumed positive.
Negative numbers are supported via the unary minus operator. Positive numbers are not explicitly supported as unsigned numbers are assumed positive.

## String Support:
Expressions can contain double or single quoted strings that are evaluated the same way as PHP evalutes strings as numbers. You can also pass strings to functions.
Expand All @@ -156,3 +158,7 @@ You can add operators, functions and variables with the public methods in MathEx
This will allow you to remove functions and operators if needed, or implement different types more simply.

Also note that you can replace an existing default operator by adding a new operator with the same regular expression string. For example if you just need to redefine TokenPlus, you can just add a new operator with the same regex string, in this case '\\+'.

## Future Enhancements

At some point this package will be upgraded to a currently supported version of PHP.
1 change: 0 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="./tests/bootstrap.php"
>

Expand Down
20 changes: 18 additions & 2 deletions src/NXP/Classes/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
use NXP\Classes\Token\TokenComma;
use NXP\Classes\Token\TokenFunction;
use NXP\Classes\Token\TokenLeftBracket;
use NXP\Classes\Token\TokenMinus;
use NXP\Classes\Token\TokenNumber;
use NXP\Classes\Token\TokenRightBracket;
use NXP\Classes\Token\TokenStringDoubleQuoted;
use NXP\Classes\Token\TokenStringSingleQuoted;
use NXP\Classes\Token\TokenVariable;
use NXP\Classes\Token\TokenStringDoubleQuoted;
use NXP\Exception\IncorrectBracketsException;
use NXP\Exception\IncorrectExpressionException;

Expand Down Expand Up @@ -66,14 +67,28 @@ public function buildReversePolishNotation($tokensStream)
{
$output = [];
$stack = [];
$lastToken = null;

foreach ($tokensStream as $token) {
if ($token instanceof TokenStringDoubleQuoted) {
$output[] = $token;
} elseif ($token instanceof TokenStringSingleQuoted) {
$output[] = $token;
} elseif ($token instanceof TokenNumber) {
$output[] = $token;
// if the number starts with a minus sign, it could be a negative number, or it could be an operator grabbed by the greedy regex
// if previous token is an operator, then it negative, otherwise remove the minus sign and put a negative operator on the stack
if ($lastToken !== null) {
$value = (int)$token->getValue();
if ($value < 0 && ! ($lastToken instanceof AbstractOperator)) {
$token = new TokenNumber(abs($value));
$output[] = $token;
$output[] = new TokenMinus('-');
} else {
$output[] = $token;
}
} else {
$output[] = $token;
}
} elseif ($token instanceof TokenVariable) {
$output[] = $token;
} elseif ($token instanceof TokenFunction) {
Expand Down Expand Up @@ -118,6 +133,7 @@ public function buildReversePolishNotation($tokensStream)
$output[] = array_pop($stack);
}
}
$lastToken = $token;
}
while (!empty($stack)) {
$token = array_pop($stack);
Expand Down
23 changes: 22 additions & 1 deletion tests/MathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public function testCalculating($expression)
public function providerExpressions()
{
return [
['-5'],
['-5+10'],
['4-5'],
['4 -5'],
['(4*2)-5'],
['(4*2) - 5'],
['4*-5'],
['4 * -5'],

['0.1 + 0.2'],
['1 + 2'],

Expand Down Expand Up @@ -80,7 +89,6 @@ public function providerExpressions()
['1 + 2 * 3 / (3 * min(1, 5) * 2 + 1)'],
['1 + 2 * 3 / (3 / min(1, 5) / 2 + 1)'],


['sin(10) * cos(50) / min(10, 20/2)'],
['sin(10) * cos(50) / min(10, (20/2))'],
['sin(10) * cos(50) / min(10, (max(10,20)/2))'],
Expand All @@ -97,6 +105,11 @@ public function providerExpressions()
['-1- -2'],
['-1/-2'],
['-1*-2'],

['(1+2+3+4-5)*7/100'],
['(1+2+3+4- 5)*7/100'],
['( 1 + 2 + 3 + 4 - 5 ) * 7 / 100'],

];
}

Expand Down Expand Up @@ -166,6 +179,14 @@ public function testEvaluateFunctionParameters()
$this->assertEquals($phpResult, $calculator->execute($expression));
}

public function testFunctionsWithQuotes()
{
$calculator = new MathExecutor();
$calculator->addFunction('concat', function($first, $second){return $first.$second;});
$this->assertEquals('testing', $calculator->execute('concat("test", "ing")'));
$this->assertEquals('testing', $calculator->execute("concat('test', 'ing')"));
}

public function testQuotes()
{
$calculator = new MathExecutor();
Expand Down

0 comments on commit ce50015

Please sign in to comment.