1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| $pattern = <<<'REGEX'
~
(?(DEFINE)
(?<lvalue> family | conditions_of_use | taxonomical_group )
(?<rvalue> " [^\\"]*+ (?s: \\ . [^\\"]* )*+ " )
(?<operator> ET | OU )
(?<operate> \s+ \g<operator> \s+ )
(?<assertion> \g<lvalue> \s* = \s* \g<rvalue> )
(?<subquery> \g<assertion> (?: \g<operate> \g<assertion> )*+ )
(?<query> (?: \g<subquery> | \( \s* \g<query> \s* \) )
(?: \g<operate> \g<query> )*+ )
# partial matches
(?<p_operate>
\s+ \g<operator> (?!\s) (*:ERR_MISSING_WS_AFTER_OPERATOR)
| (?= \g<operator> ) (*:ERR_MISSING_WS_BEFORE_OPERATOR)
| \s+ [OE] )
(?<p_assertion>
(?: \g<lvalue> \s* | \b (*ACCEPT:ERR_UNKNOW_LVALUE) )
(*ACCEPT:ERR_MISSING_EQUAL_SIGN)?? = \s*
(*ACCEPT:ERR_MISSING_RVALUE)?? \g<rvalue> )
(?<p_subquery>
\g<subquery>
(?: \g<operate> \g<p_assertion> | \g<p_operate> )
| \g<p_assertion> )
(?<p_query>
(?: \( \s* (?(?=\)) (*ACCEPT:ERR_EMPTY_SUBQUERY) ) )*?
(?: \g<query>
(?: \s* \z (*:ERR_MISSING_CLOSING_PARENTHESIS)
| \g<operate> \g<p_query>?
| \g<p_operate>
)?
| \g<p_subquery>
) )
)
\A \s* (*:ERR_UNEXPECTED_CHARACTER)
(?: \g<query> \s* \z (*:ERR_NONE) | \g<p_query> | \z (*:ERR_EMPTY_QUERY) )?
~x
REGEX;
$str = ' family="machin" ET taxonomical_group="chose" OU (conditions_of_use="bidule" OU ((((family="truc" E) OU ( )))
ET family="machin-chouette") OU taxonomical_group="truc-bidule"';
$start = microtime(true);
preg_match_all($pattern, $str, $matches, PREG_SET_ORDER);
$end = microtime(true);
var_dump($matches[0]);
printf('%.1e s', $end - $start); |