Skip to content

Commit

Permalink
Improve performance for single-character operators
Browse files Browse the repository at this point in the history
  • Loading branch information
thekid committed Jan 26, 2025
1 parent 013abc8 commit af447f3
Showing 1 changed file with 34 additions and 33 deletions.
67 changes: 34 additions & 33 deletions src/main/php/lang/ast/Tokens.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,55 +166,56 @@ public function iterator($language) {

// Handle combined operators. First, ensure we have enough bytes in our buffer
// Our longest operator is 3 characters, hardcode this here.
if (self::OPERATORS[$token]) {
if ($combined= self::OPERATORS[$token]) {
$offset--;
while ($offset + 3 > $length && $this->in->available()) {
$buffer.= $this->in->read(8192);
$length= strlen($buffer);
}
foreach (self::OPERATORS[$token] as $operator) {
foreach ($combined as $operator) {
if ($offset + strlen($operator) > $length) continue;
if (0 === substr_compare($buffer, $operator, $offset, strlen($operator))) {
$token= $operator;
break;
}
}
$offset+= strlen($token);
}

// Distinguish single- and multiline comments as well as heredoc from operators
if ('//' === $token) {
yield new Token(null, 'comment', '//'.$next("\r\n"), $line);
} else if ('/*' === $token) {
$comment= '';
do {
$chunk= $next('/');
$comment.= $chunk;
} while (null !== $chunk && '*' !== $chunk[strlen($chunk) - 1]);
$comment.= $next('/');
yield new Token(null, '*' === $comment[0] ? 'apidoc' : 'comment', '/*'.$comment, $line);
$line+= substr_count($comment, "\n");
} else if ('<<<' === $token) {
$label= $next("\r\n");
$end= trim($label, '"\'');
$l= strlen($end);
$string= "<<<{$label}";

heredoc: $token= $next("\r\n");
if (0 === substr_compare($token, $end, $p= strspn($token, ' '), $l)) {
$p+= $l;
$offset-= strlen($token) - $p;
yield new Token($language->symbol('(literal)'), 'heredoc', $string.substr($token, 0, $p), $line);
$line+= substr_count($string, "\n");
// Distinguish single- and multiline comments as well as heredoc from operators
if ('//' === $token) {
yield new Token(null, 'comment', '//'.$next("\r\n"), $line);
continue;
} else if ('/*' === $token) {
$comment= '';
do {
$chunk= $next('/');
$comment.= $chunk;
} while (null !== $chunk && '*' !== $chunk[strlen($chunk) - 1]);
$comment.= $next('/');
yield new Token(null, '*' === $comment[0] ? 'apidoc' : 'comment', '/*'.$comment, $line);
$line+= substr_count($comment, "\n");
continue;
} else if (null === $token) {
throw new FormatException('Unclosed heredoc literal starting at line '.$line);
} else if ('<<<' === $token) {
$label= $next("\r\n");
$end= trim($label, '"\'');
$l= strlen($end);
$string= "<<<{$label}";

heredoc: $token= $next("\r\n");
if (0 === substr_compare($token, $end, $p= strspn($token, ' '), $l)) {
$p+= $l;
$offset-= strlen($token) - $p;
yield new Token($language->symbol('(literal)'), 'heredoc', $string.substr($token, 0, $p), $line);
$line+= substr_count($string, "\n");
continue;
} else if (null === $token) {
throw new FormatException('Unclosed heredoc literal starting at line '.$line);
}
$string.= $token;
goto heredoc;
}
$string.= $token;
goto heredoc;
} else {
yield new Token($language->symbol($token), 'operator', $token, $line);
}
yield new Token($language->symbol($token), 'operator', $token, $line);
} else {
yield new Token($language->symbols[$token] ?? $language->symbol('(name)'), 'name', $token, $line);
}
Expand Down

0 comments on commit af447f3

Please sign in to comment.