private function getPolishNotation($text)
{
$text = trim($text);
if (mb_strpos($text, '=') === 0)
{
$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;
}
$notation = [];
$stack = [];
$prev = '';
$isFunctionArgs = function ($stack)
{
return (
isset($stack[0], $stack[1], $this->functions[$stack[1][0]]) && $stack[0][0] === '('
);
};
$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);
[$name] = explode('(', $str);
$name = trim($name);
if (isset($this->functions[$name]))
{
if ($stack)
{
while ($this->priority['f'] <= $stack[0][1])
{
$op = array_shift($stack);
$notation[] = [$op[0], self::Operation];
if (!$stack)
{
break;
}
}
}
array_unshift($stack, [$name, $this->priority['f']]);
}
else
{
$this->setError(3, $name);
return false;
}
$str = '(';
}
if ($str === '-' || $str === '+')
{
if (
$prev === ''
|| in_array($prev, ['(', ';', '=', '<=', '>=', '<>', '<', '>', '&', '+', '-', '*', '/', '^'])
)
{
$str .= 'm';
}
}
switch ($str)
{
case '(':
array_unshift($stack, ['(', $this->priority['(']]);
array_unshift($stack, ['@', $this->priority['@']]);
break;
case ')':
$hasComma = false;
$hasArguments = $prev !== '(';
//trailing comma
if ($prev === ';')
{
array_shift($stack);
}
while ($op = array_shift($stack))
{
if ($op[0] === '(')
{
break;
}
if ($op[0] === ';')
{
$hasComma = true;
}
$isInFunction = $isFunctionArgs($stack);
if (
$op[0] === '@'
&& (
(!$hasComma && !$isInFunction)
|| (!$hasArguments && $isInFunction)
)
)
{
continue;
}
$notation[] = [$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 (!$stack)
{
array_unshift($stack, [$str, $this->priority[$str]]);
if ($str === ';')
{
$notation[] = ['@', self::Operation];
}
break;
}
while ($this->priority[$str] <= $stack[0][1])
{
$op = array_shift($stack);
$notation[] = [$op[0], self::Operation];
if (!$stack)
{
break;
}
}
array_unshift($stack, [$str, $this->priority[$str]]);
break;
default:
if (mb_strpos($str, '0') === 0 || (int)$str)
{
$notation[] = [(float)$str, self::Constant];
break;
}
if (mb_strpos($str, '"') === 0 || mb_strpos($str, "'") === 0)
{
$notation[] = [mb_substr($str, 1, -1), self::Constant];
break;
}
$notation[] = [$str, self::Variable];
}
$text = mb_substr($text, mb_strlen($match[0]));
$prev = $str;
}
while ($op = array_shift($stack))
{
if ($op[0] === '(')
{
$this->setError(5);
return false;
}
$notation[] = [$op[0], self::Operation];
}
return $notation;
}