* 0.9.5-DEV
+ * added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
+ * enhanced some error messages to provide better feedback in case of parsing errors
+
* 0.9.4 (2009-12-02)
If you have custom loaders, you MUST upgrade them for this release: The
[twig]
{% set foo as 'foo' %}
+ {% set foo as [1, 2] %}
+
+ {% set foo as ['foo': 'bar] %}
+
{% set foo as 'foo' ~ 'bar' %}
{% set foo, bar as 'foo', 'bar' %}
break;
default:
- if ($token->test(Twig_Token::OPERATOR_TYPE, '('))
+ if ($token->test(Twig_Token::OPERATOR_TYPE, '['))
+ {
+ $this->parser->getStream()->next();
+ $node = $this->parseArrayExpression();
+ $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']');
+ }
+ elseif ($token->test(Twig_Token::OPERATOR_TYPE, '('))
{
$this->parser->getStream()->next();
$node = $this->parseExpression();
return $node;
}
+ public function parseArrayExpression()
+ {
+ $elements = array();
+ while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ']'))
+ {
+ if (!empty($elements))
+ {
+ $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ',');
+ }
+
+ // hash or array element?
+ if (
+ $this->parser->getStream()->test(Twig_Token::STRING_TYPE)
+ ||
+ $this->parser->getStream()->test(Twig_Token::NUMBER_TYPE)
+ )
+ {
+ if ($this->parser->getStream()->look()->test(Twig_Token::OPERATOR_TYPE, ':'))
+ {
+ // hash
+ $key = $this->parser->getStream()->next()->getValue();
+ $this->parser->getStream()->next();
+
+ $elements[$key] = $this->parseExpression();
+
+ continue;
+ }
+ $this->parser->getStream()->rewind();
+ }
+
+ $elements[] = $this->parseExpression();
+ }
+
+ return new Twig_Node_Expression_Array($elements, $this->parser->getCurrentToken()->getLine());
+ }
+
public function parsePostfixExpression($node)
{
$stop = false;
--- /dev/null
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Array extends Twig_Node_Expression
+{
+ protected $elements;
+
+ public function __construct($elements, $lineno)
+ {
+ parent::__construct($lineno);
+ $this->elements = $elements;
+ }
+
+ public function __toString()
+ {
+ $repr = array(get_class($this).'(');
+ foreach ($this->elements as $name => $node)
+ {
+ foreach (explode("\n", ' '.$name.' => '.$node) as $line)
+ {
+ $repr[] = ' '.$line;
+ }
+ }
+ $repr[] = ')';
+
+ return implode("\n", $repr);
+ }
+
+ public function compile($compiler)
+ {
+ $compiler->raw('array(');
+ $first = true;
+ foreach ($this->elements as $name => $node)
+ {
+ if (!$first)
+ {
+ $compiler->raw(', ');
+ }
+ $first = false;
+
+ $compiler
+ ->repr($name)
+ ->raw(' => ')
+ ->subcompile($node)
+ ;
+ }
+ $compiler->raw(')');
+ }
+
+ public function getElements()
+ {
+ return $this->elements;
+ }
+}
--- /dev/null
+--TEST--
+Twig supports array notation
+--TEMPLATE--
+{# empty array #}
+{{ []|join(',') }}
+
+{{ [1, 2]|join(',') }}
+{{ ['foo', "bar"]|join(',') }}
+{{ [1, 'foo': 'bar']|join(',') }}
+{{ [1, 'foo': 'bar']|keys|join(',') }}
+
+{# nested arrays #}
+{% set a as [1, 2, [1, 2], 'foo': ['foo': 'bar']] %}
+{{ a[2]|join(',') }}
+{{ a["foo"]|join(',') }}
+
+{# works even if [] is used inside the array #}
+{{ [foo[bar]]|join(',') }}
+
+{# elements can be any expression #}
+{{ ['foo'|upper, bar|upper, bar == foo]|join(',') }}
+--DATA--
+return array('bar' => 'bar', 'foo' => array('bar' => 'bar'))
+--EXPECT--
+1,2
+foo,bar
+1,bar
+0,foo
+
+
+1,2
+bar
+
+
+bar
+
+
+FOO,BAR,
}
}
-$t = new LimeTest(51);
+$t = new LimeTest(52);
$fixturesDir = realpath(dirname(__FILE__).'/../fixtures/');
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file)