public function SassScriptParser::parse in Sassy 7.3
Same name and namespace in other branches
- 7 phamlp/sass/script/SassScriptParser.php \SassScriptParser::parse()
Parse SassScript to a set of tokens in RPN using the Shunting Yard Algorithm.
Parameters
string expression to parse:
SassContext the context in which the expression is parsed:
integer the environment in which the expression is parsed:
Return value
array tokens in RPN
1 call to SassScriptParser::parse()
- SassScriptParser::evaluate in phpsass/
script/ SassScriptParser.php - Evaluate a SassScript.
File
- phpsass/
script/ SassScriptParser.php, line 121
Class
- SassScriptParser
- SassScriptParser class. Parses SassScript. SassScript is lexed into {@link http://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse Polish notation} by the SassScriptLexer and the calculated result returned. @package PHamlP @subpackage …
Code
public function parse($expression, $context, $environment = self::DEFAULT_ENV) {
$outputQueue = array();
$operatorStack = array();
$parenthesis = 0;
$tokens = $this->lexer
->lex($expression, $context);
foreach ($tokens as $i => $token) {
// If two literals/expessions are seperated by whitespace use the concat operator
if (empty($token)) {
if (isset($tokens[$i + 1])) {
if ($i > 0 && (!$tokens[$i - 1] instanceof SassScriptOperation || $tokens[$i - 1]->operator === SassScriptOperation::$operators[')'][0]) && (!$tokens[$i + 1] instanceof SassScriptOperation || $tokens[$i + 1]->operator === SassScriptOperation::$operators['('][0])) {
$token = new SassScriptOperation(SassScriptOperation::$defaultOperator, $context);
}
else {
continue;
}
}
}
elseif ($token instanceof SassScriptVariable) {
$token = $token
->evaluate($context);
$environment = self::DEFAULT_ENV;
}
// If the token is a number or function add it to the output queue.
if ($token instanceof SassLiteral || $token instanceof SassScriptFunction) {
if ($environment === self::CSS_PROPERTY && $token instanceof SassNumber && !$parenthesis) {
$token->inExpression = false;
}
array_push($outputQueue, $token);
}
elseif ($token instanceof SassScriptOperation) {
// If the token is a left parenthesis push it onto the stack.
if ($token->operator == SassScriptOperation::$operators['('][0]) {
array_push($operatorStack, $token);
$parenthesis++;
}
elseif ($token->operator == SassScriptOperation::$operators[')'][0]) {
$parenthesis--;
while ($c = count($operatorStack)) {
// If the token at the top of the stack is a left parenthesis
if ($operatorStack[$c - 1]->operator == SassScriptOperation::$operators['('][0]) {
// Pop the left parenthesis from the stack, but not onto the output queue.
array_pop($operatorStack);
break;
}
// else pop the operator off the stack onto the output queue.
array_push($outputQueue, array_pop($operatorStack));
}
// If the stack runs out without finding a left parenthesis
// there are mismatched parentheses.
if ($c == 0) {
throw new SassScriptParserException('Unmatched parentheses', $context->node);
}
}
else {
// while there is an operator, o2, at the top of the stack
while ($c = count($operatorStack)) {
$operation = $operatorStack[$c - 1];
// if o2 is left parenthesis, or
// the o1 has left associativty and greater precedence than o2, or
// the o1 has right associativity and lower or equal precedence than o2
if ($operation->operator == SassScriptOperation::$operators['('][0] || $token->associativity == 'l' && $token->precedence > $operation->precedence || $token->associativity == 'r' && $token->precedence <= $operation->precedence) {
break;
// stop checking operators
}
//pop o2 off the stack and onto the output queue
array_push($outputQueue, array_pop($operatorStack));
}
// push o1 onto the stack
array_push($operatorStack, $token);
}
}
}
// When there are no more tokens
while ($c = count($operatorStack)) {
// While there are operators on the stack:
if ($operatorStack[$c - 1]->operator !== SassScriptOperation::$operators['('][0]) {
array_push($outputQueue, array_pop($operatorStack));
}
else {
throw new SassScriptParserException('Unmatched parentheses', $context->node);
}
}
return $outputQueue;
}