Fixed comma operator
Added unit tests for expressions in function arguments. Changed array_push to $var[] = native code.
This commit is contained in:
parent
265cff175e
commit
47df3edbb6
5 changed files with 73 additions and 29 deletions
|
@ -36,21 +36,17 @@ class Calculator
|
||||||
{
|
{
|
||||||
$stack = [];
|
$stack = [];
|
||||||
foreach ($tokens as $token) {
|
foreach ($tokens as $token) {
|
||||||
if ($token instanceof TokenNumber) {
|
if ($token instanceof TokenNumber || $token instanceof TokenStringDoubleQuoted || $token instanceof TokenStringSingleQuoted) {
|
||||||
array_push($stack, $token);
|
$stack[] = $token;
|
||||||
} else if ($token instanceof TokenStringDoubleQuoted) {
|
|
||||||
array_push($stack, $token);
|
|
||||||
} else if ($token instanceof TokenStringSingleQuoted) {
|
|
||||||
array_push($stack, $token);
|
|
||||||
} else if ($token instanceof TokenVariable) {
|
} else if ($token instanceof TokenVariable) {
|
||||||
$variable = $token->getValue();
|
$variable = $token->getValue();
|
||||||
if (!array_key_exists($variable, $variables)) {
|
if (!array_key_exists($variable, $variables)) {
|
||||||
throw new UnknownVariableException($variable);
|
throw new UnknownVariableException($variable);
|
||||||
}
|
}
|
||||||
$value = $variables[$variable];
|
$value = $variables[$variable];
|
||||||
array_push($stack, new TokenNumber($value));
|
$stack[] = new TokenNumber($value);
|
||||||
} else if ($token instanceof InterfaceOperator || $token instanceof TokenFunction) {
|
} else if ($token instanceof InterfaceOperator || $token instanceof TokenFunction) {
|
||||||
array_push($stack, $token->execute($stack));
|
$stack[] = $token->execute($stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result = array_pop($stack);
|
$result = array_pop($stack);
|
||||||
|
|
|
@ -77,7 +77,7 @@ class Lexer
|
||||||
} elseif ($token instanceof TokenVariable) {
|
} elseif ($token instanceof TokenVariable) {
|
||||||
$output[] = $token;
|
$output[] = $token;
|
||||||
} elseif ($token instanceof TokenFunction) {
|
} elseif ($token instanceof TokenFunction) {
|
||||||
array_push($stack, $token);
|
$stack[] = $token;
|
||||||
} elseif ($token instanceof AbstractOperator) {
|
} elseif ($token instanceof AbstractOperator) {
|
||||||
// While we have something on the stack
|
// While we have something on the stack
|
||||||
while (($count = count($stack)) > 0
|
while (($count = count($stack)) > 0
|
||||||
|
@ -104,9 +104,12 @@ class Lexer
|
||||||
$output[] = array_pop($stack);
|
$output[] = array_pop($stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_push($stack, $token);
|
// Comma operators do nothing really, don't put them on the stack
|
||||||
|
if (! ($token instanceof TokenComma)) {
|
||||||
|
$stack[] = $token;
|
||||||
|
}
|
||||||
} elseif ($token instanceof TokenLeftBracket) {
|
} elseif ($token instanceof TokenLeftBracket) {
|
||||||
array_push($stack, $token);
|
$stack[] = $token;
|
||||||
} elseif ($token instanceof TokenRightBracket) {
|
} elseif ($token instanceof TokenRightBracket) {
|
||||||
while (($current = array_pop($stack)) && (!($current instanceof TokenLeftBracket))) {
|
while (($current = array_pop($stack)) && (!($current instanceof TokenLeftBracket))) {
|
||||||
$output[] = $current;
|
$output[] = $current;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace NXP\Classes\Token;
|
||||||
/**
|
/**
|
||||||
* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
|
* @author Alexander Kiryukhin <a.kiryukhin@mail.ru>
|
||||||
*/
|
*/
|
||||||
class TokenComma implements InterfaceToken
|
class TokenComma extends AbstractOperator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
|
@ -22,4 +22,32 @@ class TokenComma implements InterfaceToken
|
||||||
{
|
{
|
||||||
return '\,';
|
return '\,';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comma operator is lowest priority
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPriority()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAssociation()
|
||||||
|
{
|
||||||
|
return self::RIGHT_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $stack
|
||||||
|
* @return TokenNumber
|
||||||
|
*/
|
||||||
|
public function execute(&$stack)
|
||||||
|
{
|
||||||
|
// Comma operators don't do anything, stack has already executed
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ class TokenFunction extends AbstractContainerToken implements InterfaceFunction
|
||||||
$args = [];
|
$args = [];
|
||||||
list($places, $function) = $this->value;
|
list($places, $function) = $this->value;
|
||||||
for ($i = 0; $i < $places; $i++) {
|
for ($i = 0; $i < $places; $i++) {
|
||||||
$args[] = array_pop($stack)->getValue();
|
array_unshift($args, array_pop($stack)->getValue());
|
||||||
}
|
}
|
||||||
$result = call_user_func_array($function, array_reverse($args));
|
|
||||||
|
$result = call_user_func_array($function, $args);
|
||||||
|
|
||||||
return new TokenNumber($result);
|
return new TokenNumber($result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,22 @@ class MathTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals(round(100/30), $calculator->execute('round(100/30)'));
|
$this->assertEquals(round(100/30), $calculator->execute('round(100/30)'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEvaluateFunctionParameters()
|
||||||
|
{
|
||||||
|
$calculator = new MathExecutor();
|
||||||
|
$calculator->addFunction('round', function ($value, $decimals)
|
||||||
|
{
|
||||||
|
return round($value, $decimals);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$expression = 'round(100 * 1.111111, 2)';
|
||||||
|
eval('$phpResult = ' . $expression . ';');
|
||||||
|
$this->assertEquals($phpResult, $calculator->execute($expression));
|
||||||
|
$expression = 'round((100*0.04)+(((100*1.02)+0.5)*1.28),2)';
|
||||||
|
eval('$phpResult = ' . $expression . ';');
|
||||||
|
$this->assertEquals($phpResult, $calculator->execute($expression));
|
||||||
|
}
|
||||||
|
|
||||||
public function testQuotes()
|
public function testQuotes()
|
||||||
{
|
{
|
||||||
$calculator = new MathExecutor();
|
$calculator = new MathExecutor();
|
||||||
|
|
Loading…
Reference in a new issue