/** * Evaluate a Script. * * @param string $expression to parse * @param Context $context the context in which the expression is evaluated * @param int $environment the environment in which the expression is evaluated * @return Literals\Literal parsed value */ public function evaluate($expression, $context, $environment = self::DEFAULT_ENV) { self::$context = $context; $operands = []; $tokens = $this->parse($expression, $context, $environment); while (count($tokens)) { $token = array_shift($tokens); if ($token instanceof ScriptFunction) { $perform = $token->perform(); array_push($operands, $perform); } elseif ($token instanceof Literals\Literal) { if ($token instanceof Literals\SassString) { $token = new Literals\SassString($this->interpolate($token->toString(), self::$context)); } array_push($operands, $token); } else { $args = []; for ($i = 0, $c = $token->operandCount; $i < $c; $i++) { $args[] = array_pop($operands); } array_push($operands, $token->perform($args)); } } return self::makeSingular($operands); }
/** * Lex an expression into Script tokens. * * @param string $string expression to lex * @param Context $context the context in which the expression is lexed * @return array tokens */ public function lex($string, $context) { // if it's already lexed, just return it as-is if (is_object($string)) { return [$string]; } if (is_array($string)) { return $string; } $tokens = []; // whilst the string is not empty, split it into it's tokens. while ($string !== FALSE) { if (($match = $this->isWhitespace($string)) !== FALSE) { $tokens[] = NULL; } elseif (($match = ScriptFunction::isa($string)) !== FALSE) { preg_match(ScriptFunction::MATCH_FUNC, $match, $matches); $args = []; foreach (ScriptFunction::extractArgs($matches[ScriptFunction::ARGS], FALSE, $context) as $key => $expression) { $args[$key] = $this->parser->evaluate($expression, $context); } $tokens[] = new ScriptFunction($matches[ScriptFunction::NAME], $args); } elseif (($match = Literals\Boolean::isa($string)) !== FALSE) { $tokens[] = new Literals\Boolean($match); } elseif (($match = Literals\Colour::isa($string)) !== FALSE) { $tokens[] = new Literals\Colour($match); } elseif (($match = Literals\Number::isa($string)) !== FALSE) { $tokens[] = new Literals\Number($match); } elseif (($match = Literals\SassString::isa($string)) !== FALSE) { $stringed = new Literals\SassString($match); $tokens[] = !strlen($stringed->quote) && Literals\SassList::isa($string) !== FALSE && !preg_match("/^\\-\\w+\\-\\w+\$/", $stringed->value) ? new Literals\SassList($string) : $stringed; } elseif ($string == '()') { $match = $string; $tokens[] = new Literals\SassList($match); } elseif (($match = Operation::isa($string)) !== FALSE) { $tokens[] = new Operation($match); } elseif (($match = Variable::isa($string)) !== FALSE) { $tokens[] = new Variable($match); } else { $_string = $string; $match = ''; while (strlen($_string) && !$this->isWhitespace($_string)) { foreach (Operation::$inStrOperators as $operator) { if (substr($_string, 0, strlen($operator)) == $operator) { break 2; } } $match .= $_string[0]; $_string = substr($_string, 1); } $tokens[] = new Literals\SassString($match); } $string = substr($string, strlen($match)); } return $tokens; }