@@ -39,7 +39,7 @@ public function preLexComponents(string $input): string
39
39
return $ input ;
40
40
}
41
41
42
- $ this ->input = $ input ;
42
+ $ this ->input = $ input = str_replace ([ "\r\n" , "\r" ], "\n" , $ input ) ;
43
43
$ this ->length = \strlen ($ input );
44
44
$ output = '' ;
45
45
@@ -126,7 +126,8 @@ public function preLexComponents(string $input): string
126
126
// open the default block
127
127
if (!empty ($ this ->currentComponents )
128
128
&& !$ this ->currentComponents [\count ($ this ->currentComponents ) - 1 ]['hasDefaultBlock ' ]) {
129
- $ output .= $ this ->addDefaultBlock ();
129
+ $ output .= '{% block content %} ' ;
130
+ $ this ->currentComponents [\count ($ this ->currentComponents ) - 1 ]['hasDefaultBlock ' ] = true ;
130
131
}
131
132
132
133
$ attributes = $ this ->consumeAttributes ($ componentName );
@@ -182,7 +183,8 @@ public function preLexComponents(string $input): string
182
183
&& preg_match ('/\S/ ' , $ char )
183
184
&& !$ this ->check ('{% block ' )
184
185
) {
185
- $ output .= $ this ->addDefaultBlock ();
186
+ $ this ->currentComponents [\count ($ this ->currentComponents ) - 1 ]['hasDefaultBlock ' ] = true ;
187
+ $ output .= '{% block content %} ' ;
186
188
}
187
189
188
190
$ output .= $ char ;
@@ -199,29 +201,14 @@ public function preLexComponents(string $input): string
199
201
200
202
private function consumeComponentName (?string $ customExceptionMessage = null ): string
201
203
{
202
- $ start = $ this ->position ;
203
- while ($ this ->position < $ this ->length && preg_match ('/[A-Za-z0-9_:@\-.]/ ' , $ this ->input [$ this ->position ])) {
204
- ++$ this ->position ;
205
- }
204
+ if (preg_match ('/\G[A-Za-z0-9_:@\-.]+/ ' , $ this ->input , $ matches , 0 , $ this ->position )) {
205
+ $ componentName = $ matches [0 ];
206
+ $ this ->position += \strlen ($ componentName );
206
207
207
- $ componentName = substr ($ this ->input , $ start , $ this ->position - $ start );
208
-
209
- if (empty ($ componentName )) {
210
- $ exceptionMessage = $ customExceptionMessage ;
211
- if (null == $ exceptionMessage ) {
212
- $ exceptionMessage = 'Expected component name when resolving the "<twig:" syntax. ' ;
213
- }
214
- throw new SyntaxError ($ exceptionMessage , $ this ->line );
208
+ return $ componentName ;
215
209
}
216
210
217
- return $ componentName ;
218
- }
219
-
220
- private function consumeAttributeName (string $ componentName ): string
221
- {
222
- $ message = \sprintf ('Expected attribute name when parsing the "<twig:%s" syntax. ' , $ componentName );
223
-
224
- return $ this ->consumeComponentName ($ message );
211
+ throw new SyntaxError ($ customExceptionMessage ?? 'Expected component name when resolving the "<twig:" syntax. ' , $ this ->line );
225
212
}
226
213
227
214
private function consumeAttributes (string $ componentName ): string
@@ -251,7 +238,9 @@ private function consumeAttributes(string $componentName): string
251
238
$ isAttributeDynamic = true ;
252
239
}
253
240
254
- $ key = $ this ->consumeAttributeName ($ componentName );
241
+ $ message = \sprintf ('Expected attribute name when parsing the "<twig:%s" syntax. ' , $ componentName );
242
+ // was called 'consumeAttributeName'
243
+ $ key = $ this ->consumeComponentName ($ message );
255
244
256
245
// <twig:component someProp> -> someProp: true
257
246
if (!$ this ->check ('= ' )) {
@@ -290,9 +279,8 @@ private function consumeAttributes(string $componentName): string
290
279
*/
291
280
private function consume (string $ string ): bool
292
281
{
293
- $ stringLength = \strlen ($ string );
294
- if (substr ($ this ->input , $ this ->position , $ stringLength ) === $ string ) {
295
- $ this ->position += $ stringLength ;
282
+ if (str_starts_with (substr ($ this ->input , $ this ->position ), $ string )) {
283
+ $ this ->position += \strlen ($ string );
296
284
297
285
return true ;
298
286
}
@@ -325,31 +313,25 @@ private function consumeChar($validChars = null): string
325
313
*/
326
314
private function consumeUntil (string $ endString ): string
327
315
{
328
- $ start = $ this ->position ;
329
- $ endCharLength = \strlen ($ endString );
316
+ if (false === $ endPosition = strpos ($ this ->input , $ endString , $ this ->position )) {
317
+ $ start = $ this ->position ;
318
+ $ this ->position = $ this ->length ;
330
319
331
- while ($ this ->position < $ this ->length ) {
332
- if (substr ($ this ->input , $ this ->position , $ endCharLength ) === $ endString ) {
333
- break ;
334
- }
335
-
336
- if ("\n" === $ this ->input [$ this ->position ]) {
337
- ++$ this ->line ;
338
- }
339
- ++$ this ->position ;
320
+ return substr ($ this ->input , $ start );
340
321
}
341
322
342
- return substr ($ this ->input , $ start , $ this ->position - $ start );
323
+ $ content = substr ($ this ->input , $ this ->position , $ endPosition - $ this ->position );
324
+ $ this ->line += substr_count ($ content , "\n" );
325
+ $ this ->position = $ endPosition ;
326
+
327
+ return $ content ;
343
328
}
344
329
345
330
private function consumeWhitespace (): void
346
331
{
347
- while ($ this ->position < $ this ->length && preg_match ('/\s/ ' , $ this ->input [$ this ->position ])) {
348
- if ("\n" === $ this ->input [$ this ->position ]) {
349
- ++$ this ->line ;
350
- }
351
- ++$ this ->position ;
352
- }
332
+ $ whitespace = substr ($ this ->input , $ this ->position , strspn ($ this ->input , " \t\n\r\0\x0B" , $ this ->position ));
333
+ $ this ->line += substr_count ($ whitespace , "\n" );
334
+ $ this ->position += \strlen ($ whitespace );
353
335
}
354
336
355
337
/**
@@ -374,18 +356,8 @@ private function expectAndConsumeChar(string $char): void
374
356
375
357
private function check (string $ chars ): bool
376
358
{
377
- $ charsLength = \strlen ($ chars );
378
- if ($ this ->position + $ charsLength > $ this ->length ) {
379
- return false ;
380
- }
381
-
382
- for ($ i = 0 ; $ i < $ charsLength ; ++$ i ) {
383
- if ($ this ->input [$ this ->position + $ i ] !== $ chars [$ i ]) {
384
- return false ;
385
- }
386
- }
387
-
388
- return true ;
359
+ return $ this ->position + \strlen ($ chars ) <= $ this ->length
360
+ && 0 === substr_compare ($ this ->input , $ chars , $ this ->position , \strlen ($ chars ));
389
361
}
390
362
391
363
private function consumeBlock (string $ componentName ): string
@@ -409,7 +381,7 @@ private function consumeBlock(string $componentName): string
409
381
$ output = "{% block {$ blockName } %} " ;
410
382
411
383
$ closingTag = '</twig:block> ' ;
412
- if (! $ this ->doesStringEventuallyExist ( $ closingTag )) {
384
+ if (false === strpos ( $ this ->input , $ closingTag, $ this -> position )) {
413
385
throw new SyntaxError ("Expected closing tag ' {$ closingTag }' for block ' {$ blockName }'. " , $ this ->line );
414
386
}
415
387
$ blockContents = $ this ->consumeUntilEndBlock ();
@@ -448,7 +420,8 @@ private function consumeUntilEndBlock(): string
448
420
if (!$ inComment && '{% endblock %} ' === substr ($ this ->input , $ this ->position , 14 )) {
449
421
if (1 === $ depth ) {
450
422
// in this case, we want to advance ALL the way beyond the endblock
451
- $ this ->position += 14 /* strlen('{% endblock %}') */ ;
423
+ // strlen('{% endblock %}') = 14
424
+ $ this ->position += 14 ;
452
425
break ;
453
426
} else {
454
427
--$ depth ;
@@ -512,18 +485,4 @@ private function consumeAttributeValue(string $quote): string
512
485
513
486
return implode ('~ ' , $ parts );
514
487
}
515
-
516
- private function doesStringEventuallyExist (string $ needle ): bool
517
- {
518
- $ remainingString = substr ($ this ->input , $ this ->position );
519
-
520
- return str_contains ($ remainingString , $ needle );
521
- }
522
-
523
- private function addDefaultBlock (): string
524
- {
525
- $ this ->currentComponents [\count ($ this ->currentComponents ) - 1 ]['hasDefaultBlock ' ] = true ;
526
-
527
- return '{% block content %} ' ;
528
- }
529
488
}
0 commit comments