• Модуль: 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);
}