private function getPolishNotation($text)
{
$text = trim($text);
if (mb_substr($text, 0, 1) === '=')
$text = mb_substr($text, 1);
if (mb_strpos($text, '{{=') === 0 && mb_substr($text, -2) == '}}')
{
$text = mb_substr($text, 3);
$text = mb_substr($text, 0, -2);
}
if ($text == '')
{
$this->SetError(1);
return false;
}
$arPolishNotation = $arStack = [];
$prev = '';
$preg = '/
s*(s* |
s*)s* |
s*,s* | # Combine ranges of variables
s*;s* | # Combine ranges of variables
s*=s* |
s*<=s* |
s*>=s* |
s*<>s* |
s*s* |
s*&s* | # String concatenation
s*+s* | # Addition or unary plus
s*-s* |
s**s* |
s*/s* |
s*^s* | # Exponentiation
s*%s* | # Percent
s*[d.]+s* | # Numbers
s*'[^']*'s* | # String constants in apostrophes
s*"[^"]*"s* | # String constants in quotes
(s*w+s*(s*) | # Function names
s*'.CBPActivity::ValueInternalPattern.'s* | # Variables
(?.+) # Any erroneous substring
/xi';
while (preg_match($preg, $text, $match))
{
if (isset($match['error']))
{
$this->SetError(2, $match['error']);
return false;
}
$str = trim($match[0]);
if ($str === ",")
$str = ";";
if (isset($match[1]) && $match[1])
{
$str = mb_strtolower($str);
list($name, $left) = explode('(', $str);
$name = trim($name);
if (isset($this->arAvailableFunctions[$name]))
{
if (!$arStack)
{
array_unshift($arStack, [$name, $this->arPriority['f']]);
}
else
{
while ($this->arPriority['f'] <= $arStack[0][1])
{
$op = array_shift($arStack);
$arPolishNotation[] = [$op[0], self::Operation];
if (!$arStack)
break;
}
array_unshift($arStack, [$name, $this->arPriority['f']]);
}
}
else
{
$this->SetError(3, $name);
return false;
}
$str = '(';
}
if ($str == '-' || $str == '+')
{
if ($prev == '' || in_array($prev, ['(', ';', '=', '<=', '>=', '<>', '<', '>', '&', '+', '-', '*', '/', '^']))
$str .= 'm';
}
$prev = $str;
switch ($str)
{
case '(':
array_unshift($arStack, ['(', $this->arPriority['(']]);
break;
case ')':
while ($op = array_shift($arStack))
{
if ($op[0] == '(')
break;
$arPolishNotation[] = [$op[0], self::Operation];
}
if ($op == null)
{
$this->SetError(4);
return false;
}
break;
case ';' : case '=' : case '<=': case '>=':
case '<>': case '<' : case '>' : case '&' :
case '+' : case '-' : case '+m': case '-m':
case '*' : case '/' : case '^' : case '%' :
if (!$arStack)
{
array_unshift($arStack, [$str, $this->arPriority[$str]]);
break;
}
while ($this->arPriority[$str] <= $arStack[0][1])
{
$op = array_shift($arStack);
$arPolishNotation[] = [$op[0], self::Operation];
if (!$arStack)
break;
}
array_unshift($arStack, [$str, $this->arPriority[$str]]);
break;
default:
if (mb_substr($str, 0, 1) == '0' || (int) $str)
{
$arPolishNotation[] = [(float)$str, self::Constant];
break;
}
if (mb_substr($str, 0, 1) == '"' || mb_substr($str, 0, 1) == "'")
{
$arPolishNotation[] = [mb_substr($str, 1, -1), self::Constant];
break;
}
$arPolishNotation[] = [$str, self::Variable];
}
$text = mb_substr($text, mb_strlen($match[0]));
}
while ($op = array_shift($arStack))
{
if ($op[0] == '(')
{
$this->SetError(5);
return false;
}
$arPolishNotation[] = [$op[0], self::Operation];
}
return $arPolishNotation;
}