4 * This file is part of Twig.
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
11 class Twig_Tests_LexerTest
extends PHPUnit_Framework_TestCase
13 public function testNameLabelForTag()
15 $template = '{% § %}';
17 $lexer = new Twig_Lexer(new Twig_Environment());
18 $stream = $lexer->tokenize($template);
20 $stream->expect(Twig_Token
::BLOCK_START_TYPE
);
21 $this->assertSame('§', $stream->expect(Twig_Token
::NAME_TYPE
)->getValue());
24 public function testNameLabelForFunction()
26 $template = '{{ §() }}';
28 $lexer = new Twig_Lexer(new Twig_Environment());
29 $stream = $lexer->tokenize($template);
31 $stream->expect(Twig_Token
::VAR_START_TYPE
);
32 $this->assertSame('§', $stream->expect(Twig_Token
::NAME_TYPE
)->getValue());
35 public function testBracketsNesting()
37 $template = '{{ {"a":{"b":"c"}} }}';
39 $this->assertEquals(2, $this->countToken($template, Twig_Token
::PUNCTUATION_TYPE
, '{'));
40 $this->assertEquals(2, $this->countToken($template, Twig_Token
::PUNCTUATION_TYPE
, '}'));
43 protected function countToken($template, $type, $value = null)
45 $lexer = new Twig_Lexer(new Twig_Environment());
46 $stream = $lexer->tokenize($template);
50 while (!$stream->isEOF()) {
51 $token = $stream->next();
52 if ($type === $token->getType()) {
53 if (null === $value || $value === $token->getValue()) {
62 public function testLineDirective()
71 $lexer = new Twig_Lexer(new Twig_Environment());
72 $stream = $lexer->tokenize($template);
75 $this->assertSame(1, $stream->expect(Twig_Token
::TEXT_TYPE
)->getLine());
76 // \n (after {% line %})
77 $this->assertSame(10, $stream->expect(Twig_Token
::TEXT_TYPE
)->getLine());
79 $this->assertSame(11, $stream->expect(Twig_Token
::VAR_START_TYPE
)->getLine());
81 $this->assertSame(12, $stream->expect(Twig_Token
::NAME_TYPE
)->getLine());
84 public function testLineDirectiveInline()
87 . "bar{% line 10 %}{{\n"
91 $lexer = new Twig_Lexer(new Twig_Environment());
92 $stream = $lexer->tokenize($template);
95 $this->assertSame(1, $stream->expect(Twig_Token
::TEXT_TYPE
)->getLine());
97 $this->assertSame(10, $stream->expect(Twig_Token
::VAR_START_TYPE
)->getLine());
99 $this->assertSame(11, $stream->expect(Twig_Token
::NAME_TYPE
)->getLine());
102 public function testLongComments()
104 $template = '{# '.str_repeat('*', 100000).' #}';
106 $lexer = new Twig_Lexer(new Twig_Environment());
107 $lexer->tokenize($template);
109 // should not throw an exception
112 public function testLongRaw()
114 $template = '{% raw %}'.str_repeat('*', 100000).'{% endraw %}';
116 $lexer = new Twig_Lexer(new Twig_Environment());
117 $stream = $lexer->tokenize($template);
119 // should not throw an exception
122 public function testLongVar()
124 $template = '{{ '.str_repeat('x', 100000).' }}';
126 $lexer = new Twig_Lexer(new Twig_Environment());
127 $stream = $lexer->tokenize($template);
129 // should not throw an exception
132 public function testLongBlock()
134 $template = '{% '.str_repeat('x', 100000).' %}';
136 $lexer = new Twig_Lexer(new Twig_Environment());
137 $stream = $lexer->tokenize($template);
139 // should not throw an exception
142 public function testBigNumbers()
144 $template = '{{ 922337203685477580700 }}';
146 $lexer = new Twig_Lexer(new Twig_Environment());
147 $stream = $lexer->tokenize($template);
148 $node = $stream->next();
149 $node = $stream->next();
150 $this->assertEquals(922337203685477580700, $node->getValue());
153 public function testStringWithEscapedDelimiter()
156 "{{ 'foo \' bar' }}" => 'foo \' bar',
157 '{{ "foo \" bar" }}' => "foo \" bar",
159 $lexer = new Twig_Lexer(new Twig_Environment());
160 foreach ($tests as $template => $expected) {
161 $stream = $lexer->tokenize($template);
162 $stream->expect(Twig_Token
::VAR_START_TYPE
);
163 $stream->expect(Twig_Token
::STRING_TYPE
, $expected);
167 public function testStringWithInterpolation()
169 $template = 'foo {{ "bar #{ baz + 1 }" }}';
171 $lexer = new Twig_Lexer(new Twig_Environment());
172 $stream = $lexer->tokenize($template);
173 $stream->expect(Twig_Token
::TEXT_TYPE
, 'foo ');
174 $stream->expect(Twig_Token
::VAR_START_TYPE
);
175 $stream->expect(Twig_Token
::STRING_TYPE
, 'bar ');
176 $stream->expect(Twig_Token
::INTERPOLATION_START_TYPE
);
177 $stream->expect(Twig_Token
::NAME_TYPE
, 'baz');
178 $stream->expect(Twig_Token
::OPERATOR_TYPE
, '+');
179 $stream->expect(Twig_Token
::NUMBER_TYPE
, '1');
180 $stream->expect(Twig_Token
::INTERPOLATION_END_TYPE
);
181 $stream->expect(Twig_Token
::VAR_END_TYPE
);
184 public function testStringWithEscapedInterpolation()
186 $template = '{{ "bar \#{baz+1}" }}';
188 $lexer = new Twig_Lexer(new Twig_Environment());
189 $stream = $lexer->tokenize($template);
190 $stream->expect(Twig_Token
::VAR_START_TYPE
);
191 $stream->expect(Twig_Token
::STRING_TYPE
, 'bar #{baz+1}');
192 $stream->expect(Twig_Token
::VAR_END_TYPE
);
195 public function testStringWithHash()
197 $template = '{{ "bar # baz" }}';
199 $lexer = new Twig_Lexer(new Twig_Environment());
200 $stream = $lexer->tokenize($template);
201 $stream->expect(Twig_Token
::VAR_START_TYPE
);
202 $stream->expect(Twig_Token
::STRING_TYPE
, 'bar # baz');
203 $stream->expect(Twig_Token
::VAR_END_TYPE
);
207 * @expectedException Twig_Error_Syntax
208 * @expectedExceptionMessage Unclosed """
210 public function testStringWithUnterminatedInterpolation()
212 $template = '{{ "bar #{x" }}';
214 $lexer = new Twig_Lexer(new Twig_Environment());
215 $stream = $lexer->tokenize($template);
218 public function testStringWithNestedInterpolations()
220 $template = '{{ "bar #{ "foo#{bar}" }" }}';
222 $lexer = new Twig_Lexer(new Twig_Environment());
223 $stream = $lexer->tokenize($template);
224 $stream->expect(Twig_Token
::VAR_START_TYPE
);
225 $stream->expect(Twig_Token
::STRING_TYPE
, 'bar ');
226 $stream->expect(Twig_Token
::INTERPOLATION_START_TYPE
);
227 $stream->expect(Twig_Token
::STRING_TYPE
, 'foo');
228 $stream->expect(Twig_Token
::INTERPOLATION_START_TYPE
);
229 $stream->expect(Twig_Token
::NAME_TYPE
, 'bar');
230 $stream->expect(Twig_Token
::INTERPOLATION_END_TYPE
);
231 $stream->expect(Twig_Token
::INTERPOLATION_END_TYPE
);
232 $stream->expect(Twig_Token
::VAR_END_TYPE
);
235 public function testStringWithNestedInterpolationsInBlock()
237 $template = '{% foo "bar #{ "foo#{bar}" }" %}';
239 $lexer = new Twig_Lexer(new Twig_Environment());
240 $stream = $lexer->tokenize($template);
241 $stream->expect(Twig_Token
::BLOCK_START_TYPE
);
242 $stream->expect(Twig_Token
::NAME_TYPE
, 'foo');
243 $stream->expect(Twig_Token
::STRING_TYPE
, 'bar ');
244 $stream->expect(Twig_Token
::INTERPOLATION_START_TYPE
);
245 $stream->expect(Twig_Token
::STRING_TYPE
, 'foo');
246 $stream->expect(Twig_Token
::INTERPOLATION_START_TYPE
);
247 $stream->expect(Twig_Token
::NAME_TYPE
, 'bar');
248 $stream->expect(Twig_Token
::INTERPOLATION_END_TYPE
);
249 $stream->expect(Twig_Token
::INTERPOLATION_END_TYPE
);
250 $stream->expect(Twig_Token
::BLOCK_END_TYPE
);
253 public function testOperatorEndingWithALetterAtTheEndOfALine()
255 $template = "{{ 1 and\n0}}";
257 $lexer = new Twig_Lexer(new Twig_Environment());
258 $stream = $lexer->tokenize($template);
259 $stream->expect(Twig_Token
::VAR_START_TYPE
);
260 $stream->expect(Twig_Token
::NUMBER_TYPE
, 1);
261 $stream->expect(Twig_Token
::OPERATOR_TYPE
, 'and');
265 * @expectedException Twig_Error_Syntax
266 * @expectedExceptionMessage Unclosed "variable" at line 3
268 public function testUnterminatedVariable()
279 $lexer = new Twig_Lexer(new Twig_Environment());
280 $stream = $lexer->tokenize($template);
284 * @expectedException Twig_Error_Syntax
285 * @expectedExceptionMessage Unclosed "block" at line 3
287 public function testUnterminatedBlock()
298 $lexer = new Twig_Lexer(new Twig_Environment());
299 $stream = $lexer->tokenize($template);