diff options
author | Bruce Wells <brucekwells@gmail.com> | 2019-01-12 05:45:29 +0300 |
---|---|---|
committer | Bruce Wells <brucekwells@gmail.com> | 2019-01-12 05:45:29 +0300 |
commit | 145a0a136fc41dc59a78637a8e84f1c8952ecc31 (patch) | |
tree | e65b68200d122f4c8afbf772203dc63002ad3c7f | |
parent | 9684cfd1d0e61a6bfcf1a46f322f99e7b6559df5 (diff) | |
parent | 18b12aeeff34c8ac9a350165ae36f08f4138dc9c (diff) |
Merge branch 'master' of https://github.com/phpfui/MathExecutor
# Conflicts:
# src/NXP/Classes/Lexer.php
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 @@ -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 |