- Модуль: bizproc
- Путь к файлу: ~/bitrix/modules/bizproc/lib/Calc/Parser.php
- Класс: BitrixBizprocCalcParser
- Вызов: Parser::calculate
public function calculate($text)
{
if (!$notation = $this->getPolishNotation($text))
{
return null;
}
$stack = [];
foreach ($notation as $item)
{
switch ($item[1])
{
case self::Constant:
array_unshift($stack, $item[0]);
break;
case self::Variable:
array_unshift($stack, $this->getVariableValue($item[0]));
break;
case self::Operation:
switch ($item[0])
{
case '@':
$arg = array_shift($stack);
array_unshift($stack, [$arg]);
break;
case ';':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
if (!is_array($arg1) || !isset($arg1[0]))
{
$arg1 = [$arg1];
}
$arg1[] = $arg2;
array_unshift($stack, $arg1);
break;
case '=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 == $arg2);
break;
case '<=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 <= $arg2);
break;
case '>=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 >= $arg2);
break;
case '<>':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 != $arg2);
break;
case '<':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 < $arg2);
break;
case '>':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 > $arg2);
break;
case '&':
$arg2 = CBPHelper::stringify(array_shift($stack));
$arg1 = CBPHelper::stringify(array_shift($stack));
array_unshift($stack, $arg1 . $arg2);
break;
case '+':
$arg2 = (float)($this->toSingleValue(array_shift($stack)));
$arg1 = (float)($this->toSingleValue(array_shift($stack)));
array_unshift($stack, $arg1 + $arg2);
break;
case '-':
$arg2 = (float)($this->toSingleValue(array_shift($stack)));
$arg1 = (float)($this->toSingleValue(array_shift($stack)));
array_unshift($stack, $arg1 - $arg2);
break;
case '+m':
$arg = (float)array_shift($stack);
array_unshift($stack, $arg);
break;
case '-m':
$arg = (float)array_shift($stack);
array_unshift($stack, (-$arg));
break;
case '*':
$arg2 = (float)($this->toSingleValue(array_shift($stack)));
$arg1 = (float)($this->toSingleValue(array_shift($stack)));
array_unshift($stack, $arg1 * $arg2);
break;
case '/':
$arg2 = (float)($this->toSingleValue(array_shift($stack)));
$arg1 = (float)($this->toSingleValue(array_shift($stack)));
if (0 == $arg2)
{
$this->setError(6);
return null;
}
array_unshift($stack, $arg1 / $arg2);
break;
case '^':
$arg2 = (float)array_shift($stack);
$arg1 = (float)array_shift($stack);
array_unshift($stack, $arg1 ** $arg2);
break;
case '%':
$arg = (float)array_shift($stack);
array_unshift($stack, $arg / 100);
break;
default:
$func = $this->functions[$item[0]]['func'];
$functionArgs = new Arguments($this);
if (!empty($this->functions[$item[0]]['args']))
{
$args = array_shift($stack);
$functionArgs->setArgs(is_array($args) ? $args : [$args]);
}
$val = $func($functionArgs);
$error = is_float($val) && (is_nan($val) || is_infinite($val));
if ($error)
{
$this->setError(8, $item[0]);
return null;
}
array_unshift($stack, $val);
}
}
}
if (count($stack) > 1)
{
$this->setError(7);
return null;
}
return array_shift($stack);
}