8000 [ExpressionLanguage] improved performance · symfony/symfony@86ac8d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 86ac8d7

Browse files
committed
[ExpressionLanguage] improved performance
1 parent e369d14 commit 86ac8d7

File tree

2 files changed

+28
-34
lines changed

2 files changed

+28
-34
lines changed

src/Symfony/Component/ExpressionLanguage/Lexer.php

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,18 @@ class Lexer
2727
*/
2828
public function tokenize($expression)
2929
{
30-
$expression = str_replace(array("\r\n", "\r"), "\n", $expression);
30+
$expression = str_replace(array("\r", "\n", "\t", "\v", "\f"), ' ', $expression);
3131
$cursor = 0;
3232
$tokens = array();
3333
$brackets = array();
34-
$operatorRegex = $this->getOperatorRegex();
3534
$end = strlen($expression);
3635

3736
while ($cursor < $end) {
38-
if (preg_match('/\s+/A', $expression, $match, null, $cursor)) {
39-
// whitespace
40-
$cursor += strlen($match[0]);
41-
} elseif (preg_match($operatorRegex, $expression, $match, null, $cursor)) {
42-
// operators
43-
$tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1);
44-
$cursor += strlen($match[0]);
45-
} elseif (preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $expression, $match, null, $cursor)) {
46-
// names
47-
$tokens[] = new Token(Token::NAME_TYPE, $match[0], $cursor + 1);
48-
$cursor += strlen($match[0]);
49-
} elseif (preg_match('/[0-9]+(?:\.[0-9]+)?/A', $expression, $match, null, $cursor)) {
37+
while (' ' == $expression[$cursor]) {
38+
++$cursor;
39+
}
40+
41+
if (preg_match('/[0-9]+(?:\.[0-9]+)?/A', $expression, $match, null, $cursor)) {
5042
// numbers
5143
$number = (float) $match[0]; // floats
5244
if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
@@ -81,6 +73,14 @@ public function tokenize($expression)
8173
// strings
8274
$tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1);
8375
$cursor += strlen($match[0]);
76+
} elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||\!~|\=~|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, null, $cursor)) {
77+
// operators
78+
$tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1);
79+
$cursor += strlen($match[0]);
80+
} elseif (preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $expression, $match, null, $cursor)) {
81+
// names
82+
$tokens[] = new Token(Token::NAME_TYPE, $match[0], $cursor + 1);
83+
$cursor += strlen($match[0]);
8484
} else {
8585
// unlexable
8686
throw new SyntaxError(sprintf('Unexpected character "%s"', $expression[$cursor]), $cursor);
@@ -96,24 +96,4 @@ public function tokenize($expression)
9696

9797
return new TokenStream($tokens);
9898
}
99-
100-
private function getOperatorRegex()
101-
{
102-
$operators = array(
103-
'not', '!', '-', '+',
104-
'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', '=~', '!~', '**',
105-
);
106-
107-
$operators = array_combine($operators, array_map('strlen', $operators));
108-
arsort($operators);
109-
110-
$regex = array();
111-
foreach ($operators as $operator => $length) {
112-
// an operator that ends with a character must be followed by
113-
// a whitespace or a parenthesis
114-
$regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s()])' : '');
115-
}
116-
117-
return '/'.implode('|', $regex).'/A';
118-
}
11999
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
$operators = array('not', '!', 'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', '=~', '!~', '**');
4+
$operators = array_combine($operators, array_map('strlen', $operators));
5+
arsort($operators);
6+
7+
$regex = array();
8+
foreach ($operators as $operator => $length) {
9+
// an operator that ends with a character must be followed by
10+
// a whitespace or a parenthesis
11+
$regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : '');
12+
}
13+
14+
echo '/'.implode('|', $regex).'/A';

0 commit comments

Comments
 (0)
0