made operators configurable

This commit is contained in:
Fabien Potencier
2010-11-26 20:57:53 +01:00
parent f4c55791f7
commit dc71bf1a82
6 changed files with 118 additions and 58 deletions
+40
View File
@@ -30,6 +30,8 @@ class Twig_Environment
protected $runtimeInitialized;
protected $loadedTemplates;
protected $strictVariables;
protected $unaryOperators;
protected $binaryOperators;
/**
* Constructor.
@@ -414,6 +416,44 @@ class Twig_Environment
return $this->tests;
}
public function getUnaryOperators()
{
if (null === $this->unaryOperators) {
$this->initOperators();
}
return $this->unaryOperators;
}
public function getBinaryOperators()
{
if (null === $this->binaryOperators) {
$this->initOperators();
}
return $this->binaryOperators;
}
protected function initOperators()
{
$this->unaryOperators = array();
$this->binaryOperators = array();
foreach ($this->getExtensions() as $extension) {
$operators = $extension->getOperators();
if (!$operators) {
continue;
}
if (2 !== count($operators)) {
throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
}
$this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
$this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
}
}
protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
+4 -57
View File
@@ -30,47 +30,11 @@ class Twig_ExpressionParser
protected $unaryOperators;
protected $binaryOperators;
public function __construct(Twig_Parser $parser)
public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
{
$this->parser = $parser;
$this->unaryOperators = $this->getUnaryOperators();
$this->binaryOperators = $this->getBinaryOperators();
}
public function getUnaryOperators()
{
return array(
'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
'-' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Neg'),
'+' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Pos'),
);
}
public function getBinaryOperators()
{
return array(
'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => self::OPERATOR_LEFT),
'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => self::OPERATOR_LEFT),
'==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => self::OPERATOR_LEFT),
'!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => self::OPERATOR_LEFT),
'<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => self::OPERATOR_LEFT),
'>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => self::OPERATOR_LEFT),
'>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => self::OPERATOR_LEFT),
'<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => self::OPERATOR_LEFT),
'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => self::OPERATOR_LEFT),
'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => self::OPERATOR_LEFT),
'+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => self::OPERATOR_LEFT),
'-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => self::OPERATOR_LEFT),
'~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => self::OPERATOR_LEFT),
'*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => self::OPERATOR_LEFT),
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => self::OPERATOR_LEFT),
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => self::OPERATOR_LEFT),
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => self::OPERATOR_LEFT),
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => self::OPERATOR_LEFT),
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => self::OPERATOR_LEFT),
'..' => array('precedence' => 110, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => self::OPERATOR_LEFT),
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => self::OPERATOR_RIGHT),
);
$this->unaryOperators = $unaryOperators;
$this->binaryOperators = $binaryOperators;
}
public function parseExpression($precedence = 0)
@@ -82,7 +46,7 @@ class Twig_ExpressionParser
$this->parser->getStream()->next();
if (isset($op['callable'])) {
$expr = call_user_func($op['callable'], $expr);
$expr = call_user_func($op['callable'], $this->parser, $expr);
} else {
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
$class = $op['class'];
@@ -250,23 +214,6 @@ class Twig_ExpressionParser
return $node;
}
public function parseNotTestExpression($node)
{
return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
}
public function parseTestExpression($node)
{
$stream = $this->parser->getStream();
$name = $stream->expect(Twig_Token::NAME_TYPE);
$arguments = null;
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$arguments = $this->parseArguments($node);
}
return new Twig_Node_Expression_Test($node, $name->getValue(), $arguments, $this->parser->getCurrentToken()->getLine());
}
public function parseSubscriptExpression($node)
{
$token = $this->parser->getStream()->next();
+10
View File
@@ -60,4 +60,14 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
{
return array();
}
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators()
{
return array();
}
}
+56
View File
@@ -102,6 +102,62 @@ class Twig_Extension_Core extends Twig_Extension
);
}
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators()
{
return array(
array(
'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
'-' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Neg'),
'+' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Pos'),
),
array(
'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'..' => array('precedence' => 110, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
),
);
}
public function parseNotTestExpression($parser, $node)
{
return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
}
public function parseTestExpression($parser, $node)
{
$stream = $parser->getStream();
$name = $stream->expect(Twig_Token::NAME_TYPE);
$arguments = null;
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$arguments = $parser->getExpressionParser()->parseArguments($node);
}
return new Twig_Node_Expression_Test($node, $name->getValue(), $arguments, $parser->getCurrentToken()->getLine());
}
/**
* Returns the name of the extension.
*
+7
View File
@@ -54,6 +54,13 @@ interface Twig_ExtensionInterface
*/
public function getTests();
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators();
/**
* Returns the name of the extension.
*
+1 -1
View File
@@ -50,7 +50,7 @@ class Twig_Parser implements Twig_ParserInterface
$this->visitors = $this->env->getNodeVisitors();
if (null === $this->expressionParser) {
$this->expressionParser = new Twig_ExpressionParser($this);
$this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators());
}
$this->stream = $stream;