From: Fabien Potencier Date: Sat, 11 Oct 2014 22:26:35 +0000 (+0200) Subject: fixed negative number lexing X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=bf541bf2495fae9edcf45122b63f4dce2591d093;p=web%2Fkonrad%2Ftwig.git fixed negative number lexing --- diff --git a/CHANGELOG b/CHANGELOG index 9d136c1..d41ea1d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 1.16.2 (2014-XX-XX) + * fixed lexing of negative numbers * fixed macros when using an argument named like a PHP super global (like GET or POST) * fixed date_modify when working with DateTimeImmutable * optimized for loops diff --git a/lib/Twig/Lexer.php b/lib/Twig/Lexer.php index ad3ec7d..43d6daa 100644 --- a/lib/Twig/Lexer.php +++ b/lib/Twig/Lexer.php @@ -40,7 +40,7 @@ class Twig_Lexer implements Twig_LexerInterface const STATE_INTERPOLATION = 4; const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; - const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; + const REGEX_NUMBER = '/\-?[0-9]+(?:\.[0-9]+)?/A'; const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; const REGEX_DQ_STRING_DELIM = '/"/A'; const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; @@ -228,8 +228,17 @@ class Twig_Lexer implements Twig_LexerInterface } } + // numbers + if (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { + $number = (float) $match[0]; // floats + if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { + $number = (int) $match[0]; // integers lower than the maximum + } + $this->pushToken(Twig_Token::NUMBER_TYPE, $number); + $this->moveCursor($match[0]); + } // operators - if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { + elseif (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); $this->moveCursor($match[0]); } @@ -238,15 +247,6 @@ class Twig_Lexer implements Twig_LexerInterface $this->pushToken(Twig_Token::NAME_TYPE, $match[0]); $this->moveCursor($match[0]); } - // numbers - elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { - $number = (float) $match[0]; // floats - if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { - $number = (int) $match[0]; // integers lower than the maximum - } - $this->pushToken(Twig_Token::NUMBER_TYPE, $number); - $this->moveCursor($match[0]); - } // punctuation elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { // opening bracket diff --git a/test/Twig/Tests/Fixtures/expressions/negative_numbers.test b/test/Twig/Tests/Fixtures/expressions/negative_numbers.test new file mode 100644 index 0000000..3f7afda --- /dev/null +++ b/test/Twig/Tests/Fixtures/expressions/negative_numbers.test @@ -0,0 +1,13 @@ +--TEST-- +Twig manages negative numbers correctly +--TEMPLATE-- +{% import _self as macros %} +{{ macros.negative_number1() }} +{{ macros.negative_number2() }} +{% macro negative_number1(nb=-1) %}{{ nb }}{% endmacro %} +{% macro negative_number2(nb = -1) %}{{ nb }}{% endmacro %} +--DATA-- +return array() +--EXPECT-- +-1 +-1 diff --git a/test/Twig/Tests/LexerTest.php b/test/Twig/Tests/LexerTest.php index c4d7083..74e8397 100644 --- a/test/Twig/Tests/LexerTest.php +++ b/test/Twig/Tests/LexerTest.php @@ -260,6 +260,23 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase $stream->expect(Twig_Token::OPERATOR_TYPE, 'and'); } + public function testNegativeNumbers() + { + $template = "{{ -3 }}{{ 1 - 2 }}"; + + $lexer = new Twig_Lexer(new Twig_Environment()); + $stream = $lexer->tokenize($template); + $stream->expect(Twig_Token::VAR_START_TYPE); + $stream->expect(Twig_Token::NUMBER_TYPE, -3); + $stream->expect(Twig_Token::VAR_END_TYPE); + + $stream->expect(Twig_Token::VAR_START_TYPE); + $stream->expect(Twig_Token::NUMBER_TYPE, 1); + $stream->expect(Twig_Token::OPERATOR_TYPE, '-'); + $stream->expect(Twig_Token::NUMBER_TYPE, 2); + $stream->expect(Twig_Token::VAR_END_TYPE); + } + /** * @expectedException Twig_Error_Syntax * @expectedExceptionMessage Unclosed "variable" at line 3