cloudformation-plus-plus: cfn template preprocessor
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

124 lines
2.5 KiB

<?php
declare(strict_types=1);
namespace App\Engine\Cfnpp\Expression;
class Expression
{
protected $tokens;
protected $stack;
protected $variables;
public function __construct(array $tokens)
{
$this->tokens = $tokens;
}
public function evaluate(array $variables = [])
{
$this->variables = $variables;
$this->stack = [];
$tokens = $this->tokens;
while (sizeof($tokens))
{
$token = array_shift($tokens);
if ($token instanceof TokenNumericLiteral)
{
$this->evaluateTokenNumericLiteral($token);
}
elseif ($token instanceof TokenStringLiteral)
{
$this->evaluateTokenStringLiteral($token);
}
elseif ($token instanceof TokenOperator)
{
$this->evaluateTokenOperator($token);
}
elseif ($token instanceof TokenVariable)
{
$this->evaluateTokenVariable($token);
}
else
{
throw new \Exception('Unhandled expression token type: '.basename(get_class($token)));
}
}
if (sizeof($this->stack) != 1)
{
throw new \Exception('Expression did not evaluate down to a single value');
}
return $this->stack[0];
}
protected function evaluateTokenNumericLiteral(TokenNumericLiteral $token)
{
$this->push($token->getValue());
}
protected function evaluateTokenStringLiteral(TokenStringLiteral $token)
{
$this->push($token->getValue());
}
protected function evaluateTokenOperator(TokenOperator $token)
{
switch ($token->getOperator())
{
case 'eq':
$this->push($this->pop() == $this->pop());
break;
case 'neq':
$this->push($this->pop() != $this->pop());
break;
case 'gt':
$this->push($this->pop(1) > $this->pop());
break;
case 'gte':
$this->push($this->pop(1) >= $this->pop());
break;
case 'lt':
$this->push($this->pop(1) < $this->pop());
break;
case 'lte':
$this->push($this->pop(1) <= $this->pop());
break;
case 'and':
$var1 = $this->pop();
$var2 = $this->pop();
$this->push($var1 && $var2);
break;
case 'or':
$var1 = $this->pop();
$var2 = $this->pop();
$this->push($var1 || $var2);
break;
}
}
protected function evaluateTokenVariable(TokenVariable $token)
{
$name = $token->getName();
if (!isset($this->variables[$name]))
{
throw new \Exception('Undefined variable: '.$name);
}
$this->push($this->variables[$name]);
}
protected function pop(int $offset = 0)
{
return array_splice($this->stack, -1 * ($offset + 1), 1)[0];
}
protected function push($value)
{
array_push($this->stack, $value);
}
}