aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Wells <brucekwells@gmail.com>2019-01-12 05:45:29 +0300
committerBruce Wells <brucekwells@gmail.com>2019-01-12 05:45:29 +0300
commit145a0a136fc41dc59a78637a8e84f1c8952ecc31 (patch)
treee65b68200d122f4c8afbf772203dc63002ad3c7f
parent9684cfd1d0e61a6bfcf1a46f322f99e7b6559df5 (diff)
parent18b12aeeff34c8ac9a350165ae36f08f4138dc9c (diff)
Merge branch 'master' of https://github.com/phpfui/MathExecutor
# Conflicts: # src/NXP/Classes/Lexer.php
-rw-r--r--.travis.yml2
-rw-r--r--README.md21
-rw-r--r--code-of-conduct.md9
-rw-r--r--src/NXP/Classes/Calculator.php10
-rw-r--r--src/NXP/Classes/Lexer.php78
-rw-r--r--src/NXP/Classes/Token/AbstractContainerToken.php2
-rw-r--r--src/NXP/Classes/Token/AbstractOperator.php2
-rw-r--r--src/NXP/Classes/Token/InterfaceFunction.php2
-rw-r--r--src/NXP/Classes/Token/InterfaceOperator.php2
-rw-r--r--src/NXP/Classes/Token/InterfaceToken.php2
-rw-r--r--src/NXP/Classes/Token/TokenComma.php2
-rw-r--r--src/NXP/Classes/Token/TokenDegree.php2
-rw-r--r--src/NXP/Classes/Token/TokenDivision.php2
-rw-r--r--src/NXP/Classes/Token/TokenFunction.php2
-rw-r--r--src/NXP/Classes/Token/TokenLeftBracket.php2
-rw-r--r--src/NXP/Classes/Token/TokenMinus.php2
-rw-r--r--src/NXP/Classes/Token/TokenMultiply.php2
-rw-r--r--src/NXP/Classes/Token/TokenNumber.php2
-rw-r--r--src/NXP/Classes/Token/TokenPlus.php2
-rw-r--r--src/NXP/Classes/Token/TokenRightBracket.php2
-rw-r--r--src/NXP/Classes/Token/TokenStringDoubleQuoted.php (renamed from src/NXP/Classes/Token/TokenString.php)2
-rw-r--r--src/NXP/Classes/Token/TokenStringSingleQuoted.php26
-rw-r--r--src/NXP/Classes/Token/TokenVariable.php2
-rw-r--r--src/NXP/Classes/TokenFactory.php40
-rw-r--r--src/NXP/Exception/IncorrectBracketsException.php2
-rw-r--r--src/NXP/Exception/UnknownVariableException.php2
-rw-r--r--src/NXP/MathExecutor.php124
-rw-r--r--tests/MathTest.php18
28 files changed, 239 insertions, 127 deletions
diff --git a/.travis.yml b/.travis.yml
index 47d1020..551e6ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,9 @@ language: php
php:
- 5.6
+ - 7.1
- 7.2
+ - 7.3
before_script:
- wget http://getcomposer.org/composer.phar
diff --git a/README.md b/README.md
index 39490a4..b86f9c6 100644
--- a/README.md
+++ b/README.md
@@ -11,18 +11,13 @@ 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
## Install via Composer:
-Stable branch
```
composer require "nxp/math-executor"
```
-Dev branch (currently unsupported)
-```
-composer require "nxp/math-executor" "dev-dev"
-```
-
## Sample usage:
```php
require "vendor/autoload.php";
@@ -132,7 +127,7 @@ $executor->setVars([
echo $executor->execute("$var1 + $var2");
```
## Division By Zero Support:
-By default, the result of division by zero is zero and no error is generated. You have the option to thow a \NXP\Exception\DivisionByZeroException by calling setDivisionByZeroException.
+By default, the result of division by zero is zero and no error is generated. You have the option to throw a `\NXP\Exception\DivisionByZeroException` by calling `setDivisionByZeroException`.
```php
$executor->setDivisionByZeroException();
@@ -144,7 +139,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, 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.
## 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.
@@ -152,3 +147,13 @@ Expressions can contain double or single quoted strings that are evaluated the s
```php
echo $executor->execute("1 + '2.5' * '.5' + myFunction('category')");
```
+
+## Extending MathExecutor
+You can add operators, functions and variables with the public methods in MathExecutor, but if you need to do more serious modifications to base behaviours, the easiest way to extend MathExecutor is to redefine the following methods in your derived class:
+* defaultOperators
+* defaultFunctions
+* defaultVars
+
+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 '\\+'.
diff --git a/code-of-conduct.md b/code-of-conduct.md
new file mode 100644
index 0000000..83e0f4e
--- /dev/null
+++ b/code-of-conduct.md
@@ -0,0 +1,9 @@
+# Code of conduct
+
+We don't care who you are IRL. Be professional and responsible.
+
+If you are a good person, we are happy for you.
+
+If you are an asshole to us, we will be assholes in relation to you.
+
+> Do to no one what you yourself dislike \ No newline at end of file
diff --git a/src/NXP/Classes/Calculator.php b/src/NXP/Classes/Calculator.php
index 253e70c..1ceac84 100644
--- a/src/NXP/Classes/Calculator.php
+++ b/src/NXP/Classes/Calculator.php
@@ -13,13 +13,14 @@ namespace NXP\Classes;
use NXP\Classes\Token\InterfaceOperator;
use NXP\Classes\Token\TokenFunction;
use NXP\Classes\Token\TokenNumber;
-use NXP\Classes\Token\TokenString;
+use NXP\Classes\Token\TokenStringSingleQuoted;
+use NXP\Classes\Token\TokenStringDoubleQuoted;
use NXP\Classes\Token\TokenVariable;
use NXP\Exception\IncorrectExpressionException;
use NXP\Exception\UnknownVariableException;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class Calculator
{
@@ -38,7 +39,10 @@ class Calculator
if ($token instanceof TokenNumber) {
array_push($stack, $token);
}
- if ($token instanceof TokenString) {
+ if ($token instanceof TokenStringDoubleQuoted) {
+ array_push($stack, $token);
+ }
+ if ($token instanceof TokenStringSingleQuoted) {
array_push($stack, $token);
}
if ($token instanceof TokenVariable) {
diff --git a/src/NXP/Classes/Lexer.php b/src/NXP/Classes/Lexer.php
index 1650b80..a511c9b 100644
--- a/src/NXP/Classes/Lexer.php
+++ b/src/NXP/Classes/Lexer.php
@@ -17,13 +17,14 @@ use NXP\Classes\Token\TokenFunction;
use NXP\Classes\Token\TokenLeftBracket;
use NXP\Classes\Token\TokenNumber;
use NXP\Classes\Token\TokenRightBracket;
+use NXP\Classes\Token\TokenStringSingleQuoted;
use NXP\Classes\Token\TokenVariable;
-use NXP\Classes\Token\TokenString;
+use NXP\Classes\Token\TokenStringDoubleQuoted;
use NXP\Exception\IncorrectBracketsException;
use NXP\Exception\IncorrectExpressionException;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class Lexer
{
@@ -38,9 +39,8 @@ class Lexer
}
/**
- * @param string $input Source string of equation
- * @return array Tokens stream
- * @throws \NXP\Exception\IncorrectExpressionException
+ * @param string $input Source string of equation
+ * @return array Tokens stream
*/
public function stringToTokensStream($input)
{
@@ -58,9 +58,9 @@ class Lexer
}
/**
- * @param array $tokensStream Tokens stream
- * @return array Array of tokens in revers polish notation
- * @throws \NXP\Exception\IncorrectExpressionException
+ * @param array $tokensStream Tokens stream
+ * @return array Array of tokens in revers polish notation
+ * @throws IncorrectBracketsException
*/
public function buildReversePolishNotation($tokensStream)
{
@@ -68,54 +68,50 @@ class Lexer
$stack = [];
foreach ($tokensStream as $token) {
- if ($token instanceof TokenString) {
+ if ($token instanceof TokenStringDoubleQuoted) {
$output[] = $token;
- }
- elseif ($token instanceof TokenNumber) {
+ } elseif ($token instanceof TokenStringSingleQuoted) {
$output[] = $token;
- }
- elseif ($token instanceof TokenVariable) {
+ } elseif ($token instanceof TokenNumber) {
$output[] = $token;
- }
- elseif ($token instanceof TokenFunction) {
+ } elseif ($token instanceof TokenVariable) {
+ $output[] = $token;
+ } elseif ($token instanceof TokenFunction) {
array_push($stack, $token);
- }
- elseif ($token instanceof AbstractOperator) {
+ } elseif ($token instanceof AbstractOperator) {
// While we have something on the stack
while (($count = count($stack)) > 0
- && (
- // If it is a function
- ($stack[$count-1] instanceof TokenFunction)
+ && (
+ // If it is a function
+ ($stack[$count - 1] instanceof TokenFunction)
- ||
- // Or the operator at the top of the operator stack
- // has (left associative and equal precedence)
- // or has greater precedence
- (($stack[$count-1] instanceof InterfaceOperator) &&
- (
- ($stack[$count-1]->getAssociation() == AbstractOperator::LEFT_ASSOC &&
- $token->getPriority() == $stack[$count-1]->getPriority())
- ||
- ($stack[$count-1]->getPriority() > $token->getPriority())
- )
- )
- )
+ ||
+ // Or the operator at the top of the operator stack
+ // has (left associative and equal precedence)
+ // or has greater precedence
+ (($stack[$count - 1] instanceof InterfaceOperator) &&
+ (
+ ($stack[$count - 1]->getAssociation() == AbstractOperator::LEFT_ASSOC &&
+ $token->getPriority() == $stack[$count - 1]->getPriority())
+ ||
+ ($stack[$count - 1]->getPriority() > $token->getPriority())
+ )
+ )
+ )
- // And not a left bracket
- && ( ! ($stack[$count-1] instanceof TokenLeftBracket)) ) {
+ // And not a left bracket
+ && (!($stack[$count - 1] instanceof TokenLeftBracket))) {
$output[] = array_pop($stack);
}
array_push($stack, $token);
- }
- elseif ($token instanceof TokenLeftBracket) {
+ } elseif ($token instanceof TokenLeftBracket) {
array_push($stack, $token);
- }
- elseif ($token instanceof TokenRightBracket) {
- while (($current = array_pop($stack)) && ( ! ($current instanceof TokenLeftBracket))) {
+ } elseif ($token instanceof TokenRightBracket) {
+ while (($current = array_pop($stack)) && (!($current instanceof TokenLeftBracket))) {
$output[] = $current;
}
- if (!empty($stack) && ($stack[count($stack)-1] instanceof TokenFunction)) {
+ if (!empty($stack) && ($stack[count($stack) - 1] instanceof TokenFunction)) {
$output[] = array_pop($stack);
}
}
diff --git a/src/NXP/Classes/Token/AbstractContainerToken.php b/src/NXP/Classes/Token/AbstractContainerToken.php
index 12d49d2..be2da5f 100644
--- a/src/NXP/Classes/Token/AbstractContainerToken.php
+++ b/src/NXP/Classes/Token/AbstractContainerToken.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
abstract class AbstractContainerToken implements InterfaceToken
{
diff --git a/src/NXP/Classes/Token/AbstractOperator.php b/src/NXP/Classes/Token/AbstractOperator.php
index 87634d5..8b23ad8 100644
--- a/src/NXP/Classes/Token/AbstractOperator.php
+++ b/src/NXP/Classes/Token/AbstractOperator.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
abstract class AbstractOperator implements InterfaceToken, InterfaceOperator
{
diff --git a/src/NXP/Classes/Token/InterfaceFunction.php b/src/NXP/Classes/Token/InterfaceFunction.php
index be867b0..a457d0e 100644
--- a/src/NXP/Classes/Token/InterfaceFunction.php
+++ b/src/NXP/Classes/Token/InterfaceFunction.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
interface InterfaceFunction
{
diff --git a/src/NXP/Classes/Token/InterfaceOperator.php b/src/NXP/Classes/Token/InterfaceOperator.php
index da6cdf0..9e3bae1 100644
--- a/src/NXP/Classes/Token/InterfaceOperator.php
+++ b/src/NXP/Classes/Token/InterfaceOperator.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
interface InterfaceOperator
{
diff --git a/src/NXP/Classes/Token/InterfaceToken.php b/src/NXP/Classes/Token/InterfaceToken.php
index 86fec91..db07aeb 100644
--- a/src/NXP/Classes/Token/InterfaceToken.php
+++ b/src/NXP/Classes/Token/InterfaceToken.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
interface InterfaceToken
{
diff --git a/src/NXP/Classes/Token/TokenComma.php b/src/NXP/Classes/Token/TokenComma.php
index f590e32..6a45595 100644
--- a/src/NXP/Classes/Token/TokenComma.php
+++ b/src/NXP/Classes/Token/TokenComma.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenComma implements InterfaceToken
{
diff --git a/src/NXP/Classes/Token/TokenDegree.php b/src/NXP/Classes/Token/TokenDegree.php
index 3eec23d..273183a 100644
--- a/src/NXP/Classes/Token/TokenDegree.php
+++ b/src/NXP/Classes/Token/TokenDegree.php
@@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
use NXP\Exception\IncorrectExpressionException;
/**
-* @author Alexander Kiryukhin <alexander@symdev.org>
+* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenDegree extends AbstractOperator
{
diff --git a/src/NXP/Classes/Token/TokenDivision.php b/src/NXP/Classes/Token/TokenDivision.php
index 9166d34..4a8f8ce 100644
--- a/src/NXP/Classes/Token/TokenDivision.php
+++ b/src/NXP/Classes/Token/TokenDivision.php
@@ -14,7 +14,7 @@ use NXP\Exception\IncorrectExpressionException;
use NXP\Exception\DivisionByZeroException;
/**
-* @author Alexander Kiryukhin <alexander@symdev.org>
+* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenDivision extends AbstractOperator
{
diff --git a/src/NXP/Classes/Token/TokenFunction.php b/src/NXP/Classes/Token/TokenFunction.php
index 2ed8ace..b2866c3 100644
--- a/src/NXP/Classes/Token/TokenFunction.php
+++ b/src/NXP/Classes/Token/TokenFunction.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenFunction extends AbstractContainerToken implements InterfaceFunction
{
diff --git a/src/NXP/Classes/Token/TokenLeftBracket.php b/src/NXP/Classes/Token/TokenLeftBracket.php
index 0cfdc1a..08165d8 100644
--- a/src/NXP/Classes/Token/TokenLeftBracket.php
+++ b/src/NXP/Classes/Token/TokenLeftBracket.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenLeftBracket implements InterfaceToken
{
diff --git a/src/NXP/Classes/Token/TokenMinus.php b/src/NXP/Classes/Token/TokenMinus.php
index 566c950..ad0b8e5 100644
--- a/src/NXP/Classes/Token/TokenMinus.php
+++ b/src/NXP/Classes/Token/TokenMinus.php
@@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
use NXP\Exception\IncorrectExpressionException;
/**
-* @author Alexander Kiryukhin <alexander@symdev.org>
+* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenMinus extends AbstractOperator
{
diff --git a/src/NXP/Classes/Token/TokenMultiply.php b/src/NXP/Classes/Token/TokenMultiply.php
index 8b173b9..0b1ecfb 100644
--- a/src/NXP/Classes/Token/TokenMultiply.php
+++ b/src/NXP/Classes/Token/TokenMultiply.php
@@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
use NXP\Exception\IncorrectExpressionException;
/**
-* @author Alexander Kiryukhin <alexander@symdev.org>
+* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenMultiply extends AbstractOperator
{
diff --git a/src/NXP/Classes/Token/TokenNumber.php b/src/NXP/Classes/Token/TokenNumber.php
index a7eac57..982e316 100644
--- a/src/NXP/Classes/Token/TokenNumber.php
+++ b/src/NXP/Classes/Token/TokenNumber.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenNumber extends AbstractContainerToken
{
diff --git a/src/NXP/Classes/Token/TokenPlus.php b/src/NXP/Classes/Token/TokenPlus.php
index fe5a1d6..a6e5036 100644
--- a/src/NXP/Classes/Token/TokenPlus.php
+++ b/src/NXP/Classes/Token/TokenPlus.php
@@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
use NXP\Exception\IncorrectExpressionException;
/**
-* @author Alexander Kiryukhin <alexander@symdev.org>
+* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenPlus extends AbstractOperator
{
diff --git a/src/NXP/Classes/Token/TokenRightBracket.php b/src/NXP/Classes/Token/TokenRightBracket.php
index c68473a..306ae0b 100644
--- a/src/NXP/Classes/Token/TokenRightBracket.php
+++ b/src/NXP/Classes/Token/TokenRightBracket.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenRightBracket implements InterfaceToken
{
diff --git a/src/NXP/Classes/Token/TokenString.php b/src/NXP/Classes/Token/TokenStringDoubleQuoted.php
index cab0711..6cff262 100644
--- a/src/NXP/Classes/Token/TokenString.php
+++ b/src/NXP/Classes/Token/TokenStringDoubleQuoted.php
@@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
/**
* @author Bruce Wells <brucekwells@gmail.com>
*/
-class TokenString extends AbstractContainerToken
+class TokenStringDoubleQuoted extends AbstractContainerToken
{
/**
* @return string
diff --git a/src/NXP/Classes/Token/TokenStringSingleQuoted.php b/src/NXP/Classes/Token/TokenStringSingleQuoted.php
new file mode 100644
index 0000000..7a7ab92
--- /dev/null
+++ b/src/NXP/Classes/Token/TokenStringSingleQuoted.php
@@ -0,0 +1,26 @@
+<?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\Classes\Token;
+
+/**
+ * @author Bruce Wells <brucekwells@gmail.com>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
+ */
+class TokenStringSingleQuoted extends AbstractContainerToken
+{
+ /**
+ * @return string
+ */
+ public static function getRegex()
+ {
+ return "'([^']|'')*'";
+ }
+}
diff --git a/src/NXP/Classes/Token/TokenVariable.php b/src/NXP/Classes/Token/TokenVariable.php
index ccd7c83..a4a820a 100644
--- a/src/NXP/Classes/Token/TokenVariable.php
+++ b/src/NXP/Classes/Token/TokenVariable.php
@@ -11,7 +11,7 @@
namespace NXP\Classes\Token;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenVariable extends AbstractContainerToken
{
diff --git a/src/NXP/Classes/TokenFactory.php b/src/NXP/Classes/TokenFactory.php
index 6956f31..74b5789 100644
--- a/src/NXP/Classes/TokenFactory.php
+++ b/src/NXP/Classes/TokenFactory.php
@@ -16,14 +16,15 @@ use NXP\Classes\Token\TokenFunction;
use NXP\Classes\Token\TokenLeftBracket;
use NXP\Classes\Token\TokenNumber;
use NXP\Classes\Token\TokenRightBracket;
+use NXP\Classes\Token\TokenStringSingleQuoted;
use NXP\Classes\Token\TokenVariable;
-use NXP\Classes\Token\TokenString;
+use NXP\Classes\Token\TokenStringDoubleQuoted;
use NXP\Exception\UnknownFunctionException;
use NXP\Exception\UnknownOperatorException;
use NXP\Exception\UnknownTokenException;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class TokenFactory
{
@@ -50,12 +51,17 @@ class TokenFactory
/**
* Add function
- * @param string $name
+ * @param string $name
* @param callable $function
- * @param int $places
+ * @param int $places
+ * @throws \ReflectionException
*/
- public function addFunction($name, callable $function, $places = 1)
+ public function addFunction($name, callable $function, $places = null)
{
+ if ($places === null) {
+ $reflector = new \ReflectionFunction($function);
+ $places = $reflector->getNumberOfParameters();
+ }
$this->functions[$name] = [$places, $function];
}
@@ -72,8 +78,9 @@ class TokenFactory
/**
* Add operator
- * @param string $operatorClass
- * @throws \NXP\Exception\UnknownOperatorException
+ * @param string $operatorClass
+ * @throws UnknownOperatorException
+ * @throws \ReflectionException
*/
public function addOperator($operatorClass)
{
@@ -83,8 +90,7 @@ class TokenFactory
throw new UnknownOperatorException($operatorClass);
}
- $this->operators[] = $operatorClass;
- $this->operators = array_unique($this->operators);
+ $this->operators[$operatorClass::getRegex()] = $operatorClass;
}
/**
@@ -131,9 +137,10 @@ class TokenFactory
}
return sprintf(
- '/(%s)|(%s)|([%s])|(%s)|(%s)|([%s%s%s])/i',
+ '/(%s)|(%s)|(%s)|([%s])|(%s)|(%s)|([%s%s%s])/i',
TokenNumber::getRegex(),
- TokenString::getRegex(),
+ TokenStringDoubleQuoted::getRegex(),
+ TokenStringSingleQuoted::getRegex(),
$operatorsRegex,
TokenFunction::getRegex(),
TokenVariable::getRegex(),
@@ -144,9 +151,10 @@ class TokenFactory
}
/**
- * @param string $token
+ * @param string $token
* @return InterfaceToken
* @throws UnknownTokenException
+ * @throws UnknownFunctionException
*/
public function createToken($token)
{
@@ -163,7 +171,11 @@ class TokenFactory
}
if ($token[0] == '"') {
- return new TokenString(str_replace('"', '', $token));
+ return new TokenStringDoubleQuoted(str_replace('"', '', $token));
+ }
+
+ if ($token[0] == "'") {
+ return new TokenStringSingleQuoted(str_replace("'", '', $token));
}
if ($token == ',') {
@@ -180,7 +192,7 @@ class TokenFactory
$regex = sprintf('/%s/i', TokenVariable::getRegex());
if (preg_match($regex, $token)) {
- return new TokenVariable(substr($token,1));
+ return new TokenVariable(substr($token, 1));
}
$regex = sprintf('/%s/i', TokenFunction::getRegex());
diff --git a/src/NXP/Exception/IncorrectBracketsException.php b/src/NXP/Exception/IncorrectBracketsException.php
index b3e8315..3b2d2b7 100644
--- a/src/NXP/Exception/IncorrectBracketsException.php
+++ b/src/NXP/Exception/IncorrectBracketsException.php
@@ -12,7 +12,7 @@
namespace NXP\Exception;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class IncorrectBracketsException extends MathExecutorException
{
diff --git a/src/NXP/Exception/UnknownVariableException.php b/src/NXP/Exception/UnknownVariableException.php
index 8c215db..031a603 100644
--- a/src/NXP/Exception/UnknownVariableException.php
+++ b/src/NXP/Exception/UnknownVariableException.php
@@ -12,7 +12,7 @@
namespace NXP\Exception;
/**
- * @author Alexander Kiryukhin <alexander@symdev.org>
+ * @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
*/
class UnknownVariableException extends MathExecutorException
{
diff --git a/src/NXP/MathExecutor.php b/src/NXP/MathExecutor.php
index fbf6ab1..29c6a64 100644
--- a/src/NXP/MathExecutor.php
+++ b/src/NXP/MathExecutor.php
@@ -13,7 +13,6 @@ namespace NXP;
use NXP\Classes\Calculator;
use NXP\Classes\Lexer;
-use NXP\Classes\Token;
use NXP\Classes\TokenFactory;
use NXP\Exception\UnknownVariableException;
@@ -54,35 +53,6 @@ class MathExecutor
}
/**
- * Set default operands and functions
- */
- protected function addDefaults()
- {
- $this->tokenFactory = new TokenFactory();
-
- $this->tokenFactory->addOperator('NXP\Classes\Token\TokenPlus');
- $this->tokenFactory->addOperator('NXP\Classes\Token\TokenMinus');
- $this->tokenFactory->addOperator('NXP\Classes\Token\TokenMultiply');
- $this->tokenFactory->addOperator('NXP\Classes\Token\TokenDivision');
- $this->tokenFactory->addOperator('NXP\Classes\Token\TokenDegree');
-
- $this->tokenFactory->addFunction('sin', 'sin');
- $this->tokenFactory->addFunction('cos', 'cos');
- $this->tokenFactory->addFunction('tn', 'tan');
- $this->tokenFactory->addFunction('asin', 'asin');
- $this->tokenFactory->addFunction('acos', 'acos');
- $this->tokenFactory->addFunction('atn', 'atan');
- $this->tokenFactory->addFunction('min', 'min', 2);
- $this->tokenFactory->addFunction('max', 'max', 2);
- $this->tokenFactory->addFunction('avg', function($arg1, $arg2) { return ($arg1 + $arg2) / 2; }, 2);
-
- $this->setVars([
- 'pi' => 3.14159265359,
- 'e' => 2.71828182846
- ]);
- }
-
- /**
* Get all vars
*
* @return array
@@ -95,13 +65,13 @@ class MathExecutor
/**
* Get a specific var
*
- * @param string $variable
+ * @param string $variable
* @return integer|float
* @throws UnknownVariableException
*/
public function getVar($variable)
{
- if (! isset($this->variables[$variable])) {
+ if (!isset($this->variables[$variable])) {
throw new UnknownVariableException("Variable ({$variable}) not set");
}
@@ -111,9 +81,10 @@ class MathExecutor
/**
* Add variable to executor
*
- * @param string $variable
+ * @param string $variable
* @param integer|float $value
* @return MathExecutor
+ * @throws \Exception
*/
public function setVar($variable, $value)
{
@@ -129,9 +100,10 @@ class MathExecutor
/**
* Add variables to executor
*
- * @param array $variables
- * @param bool $clear Clear previous variables
+ * @param array $variables
+ * @param bool $clear Clear previous variables
* @return MathExecutor
+ * @throws \Exception
*/
public function setVars(array $variables, $clear = true)
{
@@ -149,7 +121,7 @@ class MathExecutor
/**
* Remove variable from executor
*
- * @param string $variable
+ * @param string $variable
* @return MathExecutor
*/
public function removeVar($variable)
@@ -172,8 +144,9 @@ class MathExecutor
/**
* Add operator to executor
*
- * @param string $operatorClass Class of operator token
+ * @param string $operatorClass Class of operator token
* @return MathExecutor
+ * @throws Exception\UnknownOperatorException
*/
public function addOperator($operatorClass)
{
@@ -195,10 +168,11 @@ class MathExecutor
/**
* Add function to executor
*
- * @param string $name Name of function
- * @param callable $function Function
- * @param int $places Count of arguments
+ * @param string $name Name of function
+ * @param callable $function Function
+ * @param int $places Count of arguments
* @return MathExecutor
+ * @throws \ReflectionException
*/
public function addFunction($name, $function = null, $places = 1)
{
@@ -262,4 +236,74 @@ class MathExecutor
return $result;
}
+
+ /**
+ * Set default operands and functions
+ */
+ protected function addDefaults()
+ {
+ $this->tokenFactory = new TokenFactory();
+
+ foreach ($this->defaultOperators() as $operatorClass) {
+ $this->tokenFactory->addOperator($operatorClass);
+ }
+
+ foreach ($this->defaultFunctions() as $name => $callable) {
+ $this->tokenFactory->addFunction($name, $callable);
+ }
+
+ $this->setVars($this->defaultVars());
+ }
+
+ protected function defaultOperators()
+ {
+ return [
+ 'NXP\Classes\Token\TokenPlus',
+ 'NXP\Classes\Token\TokenMinus',
+ 'NXP\Classes\Token\TokenMultiply',
+ 'NXP\Classes\Token\TokenDivision',
+ 'NXP\Classes\Token\TokenDegree',
+ ];
+ }
+
+ protected function defaultFunctions()
+ {
+ return [
+ 'sin' => function ($arg) {
+ return sin($arg);
+ },
+ 'cos' => function ($arg) {
+ return cos($arg);
+ },
+ 'tn' => function ($arg) {
+ return tan($arg);
+ },
+ 'asin' => function ($arg) {
+ return asin($arg);
+ },
+ 'acos' => function ($arg) {
+ return acos($arg);
+ },
+ 'atn' => function ($arg) {
+ return atan($arg);
+ },
+ 'min' => function ($arg1, $arg2) {
+ return min($arg1, $arg2);
+ },
+ 'max' => function ($arg1, $arg2) {
+ return max($arg1, $arg2);
+ },
+ 'avg' => function ($arg1, $arg2) {
+ return ($arg1 + $arg2) / 2;
+ },
+ ];
+ }
+
+ protected function defaultVars()
+ {
+ return [
+ 'pi' => 3.14159265359,
+ 'e' => 2.71828182846
+ ];
+ }
}
diff --git a/tests/MathTest.php b/tests/MathTest.php
index 9acdb63..55e0799 100644
--- a/tests/MathTest.php
+++ b/tests/MathTest.php
@@ -32,7 +32,7 @@ class MathTest extends \PHPUnit_Framework_TestCase
/** @var float $phpResult */
eval('$phpResult = ' . $expression . ';');
- $this->assertEquals($calculator->execute($expression), $phpResult);
+ $this->assertEquals($calculator->execute($expression), $phpResult, "Expression was: ${expression}");
}
/**
@@ -138,9 +138,23 @@ class MathTest extends \PHPUnit_Framework_TestCase
{
$calculator = new MathExecutor();
- $calculator->addFunction('round', function ($arg) { return round($arg); }, 1);
+ $calculator->addFunction('round', function ($arg) {
+ return round($arg);
+ }, 1);
/** @var float $phpResult */
eval('$phpResult = round(100/30);');
$this->assertEquals($calculator->execute('round(100/30)'), $phpResult);
}
+
+ 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);
+ $calculator->execute('test("' . $testString . '")'); // single quotes
+ $calculator->execute("test('" . $testString . "')"); // double quotes
+ }
} \ No newline at end of file