Skip to content

Commit

Permalink
[TwigComponent] Optimize TwigPreLexer
Browse files Browse the repository at this point in the history
  • Loading branch information
smnandre committed Nov 4, 2024
1 parent a2f4b13 commit be9fe3c
Showing 1 changed file with 32 additions and 73 deletions.
105 changes: 32 additions & 73 deletions src/TwigComponent/src/Twig/TwigPreLexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function preLexComponents(string $input): string
return $input;
}

$this->input = $input;
$this->input = $input = str_replace(["\r\n", "\r"], "\n", $input);
$this->length = \strlen($input);
$output = '';

Expand Down Expand Up @@ -126,7 +126,8 @@ public function preLexComponents(string $input): string
// open the default block
if (!empty($this->currentComponents)
&& !$this->currentComponents[\count($this->currentComponents) - 1]['hasDefaultBlock']) {
$output .= $this->addDefaultBlock();
$output .= '{% block content %}';
$this->currentComponents[\count($this->currentComponents) - 1]['hasDefaultBlock'] = true;
}

$attributes = $this->consumeAttributes($componentName);
Expand Down Expand Up @@ -182,7 +183,8 @@ public function preLexComponents(string $input): string
&& preg_match('/\S/', $char)
&& !$this->check('{% block')
) {
$output .= $this->addDefaultBlock();
$this->currentComponents[\count($this->currentComponents) - 1]['hasDefaultBlock'] = true;
$output .= '{% block content %}';
}

$output .= $char;
Expand All @@ -199,29 +201,14 @@ public function preLexComponents(string $input): string

private function consumeComponentName(?string $customExceptionMessage = null): string
{
$start = $this->position;
while ($this->position < $this->length && preg_match('/[A-Za-z0-9_:@\-.]/', $this->input[$this->position])) {
++$this->position;
}
if (preg_match('/\G[A-Za-z0-9_:@\-.]+/', $this->input, $matches, 0, $this->position)) {
$componentName = $matches[0];
$this->position += \strlen($componentName);

$componentName = substr($this->input, $start, $this->position - $start);

if (empty($componentName)) {
$exceptionMessage = $customExceptionMessage;
if (null == $exceptionMessage) {
$exceptionMessage = 'Expected component name when resolving the "<twig:" syntax.';
}
throw new SyntaxError($exceptionMessage, $this->line);
return $componentName;
}

return $componentName;
}

private function consumeAttributeName(string $componentName): string
{
$message = \sprintf('Expected attribute name when parsing the "<twig:%s" syntax.', $componentName);

return $this->consumeComponentName($message);
throw new SyntaxError($customExceptionMessage ?? 'Expected component name when resolving the "<twig:" syntax.', $this->line);
}

private function consumeAttributes(string $componentName): string
Expand Down Expand Up @@ -251,7 +238,9 @@ private function consumeAttributes(string $componentName): string
$isAttributeDynamic = true;
}

$key = $this->consumeAttributeName($componentName);
$message = \sprintf('Expected attribute name when parsing the "<twig:%s" syntax.', $componentName);
// was called 'consumeAttributeName'
$key = $this->consumeComponentName($message);

// <twig:component someProp> -> someProp: true
if (!$this->check('=')) {
Expand Down Expand Up @@ -290,9 +279,8 @@ private function consumeAttributes(string $componentName): string
*/
private function consume(string $string): bool
{
$stringLength = \strlen($string);
if (substr($this->input, $this->position, $stringLength) === $string) {
$this->position += $stringLength;
if (str_starts_with(substr($this->input, $this->position), $string)) {
$this->position += \strlen($string);

return true;
}
Expand Down Expand Up @@ -325,31 +313,25 @@ private function consumeChar($validChars = null): string
*/
private function consumeUntil(string $endString): string
{
$start = $this->position;
$endCharLength = \strlen($endString);
if (false === $endPosition = strpos($this->input, $endString, $this->position)) {
$start = $this->position;
$this->position = $this->length;

while ($this->position < $this->length) {
if (substr($this->input, $this->position, $endCharLength) === $endString) {
break;
}

if ("\n" === $this->input[$this->position]) {
++$this->line;
}
++$this->position;
return substr($this->input, $start);
}

return substr($this->input, $start, $this->position - $start);
$content = substr($this->input, $this->position, $endPosition - $this->position);
$this->line += substr_count($content, "\n");
$this->position = $endPosition;

return $content;
}

private function consumeWhitespace(): void
{
while ($this->position < $this->length && preg_match('/\s/', $this->input[$this->position])) {
if ("\n" === $this->input[$this->position]) {
++$this->line;
}
++$this->position;
}
$whitespace = substr($this->input, $this->position, strspn($this->input, " \t\n\r\0\x0B", $this->position));
$this->line += substr_count($whitespace, "\n");
$this->position += \strlen($whitespace);
}

/**
Expand All @@ -374,18 +356,8 @@ private function expectAndConsumeChar(string $char): void

private function check(string $chars): bool
{
$charsLength = \strlen($chars);
if ($this->position + $charsLength > $this->length) {
return false;
}

for ($i = 0; $i < $charsLength; ++$i) {
if ($this->input[$this->position + $i] !== $chars[$i]) {
return false;
}
}

return true;
return $this->position + \strlen($chars) <= $this->length
&& 0 === substr_compare($this->input, $chars, $this->position, \strlen($chars));
}

private function consumeBlock(string $componentName): string
Expand All @@ -409,7 +381,7 @@ private function consumeBlock(string $componentName): string
$output = "{% block {$blockName} %}";

$closingTag = '</twig:block>';
if (!$this->doesStringEventuallyExist($closingTag)) {
if (false === strpos($this->input, $closingTag, $this->position)) {
throw new SyntaxError("Expected closing tag '{$closingTag}' for block '{$blockName}'.", $this->line);
}
$blockContents = $this->consumeUntilEndBlock();
Expand Down Expand Up @@ -448,7 +420,8 @@ private function consumeUntilEndBlock(): string
if (!$inComment && '{% endblock %}' === substr($this->input, $this->position, 14)) {
if (1 === $depth) {
// in this case, we want to advance ALL the way beyond the endblock
$this->position += 14 /* strlen('{% endblock %}') */;
// strlen('{% endblock %}') = 14
$this->position += 14;
break;
} else {
--$depth;
Expand Down Expand Up @@ -512,18 +485,4 @@ private function consumeAttributeValue(string $quote): string

return implode('~', $parts);
}

private function doesStringEventuallyExist(string $needle): bool
{
$remainingString = substr($this->input, $this->position);

return str_contains($remainingString, $needle);
}

private function addDefaultBlock(): string
{
$this->currentComponents[\count($this->currentComponents) - 1]['hasDefaultBlock'] = true;

return '{% block content %}';
}
}

0 comments on commit be9fe3c

Please sign in to comment.