diff options
-rw-r--r-- | src/Components/Condition.php | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/src/Components/Condition.php b/src/Components/Condition.php index 9d7d586..80c40f5 100644 --- a/src/Components/Condition.php +++ b/src/Components/Condition.php @@ -30,17 +30,18 @@ class Condition extends Component * * @var array */ - public static $DELIMITERS = array('&&', 'AND', 'OR', 'XOR', '||'); + public static $DELIMITERS = array('&&', '||', 'AND', 'OR', 'XOR'); /** - * Hash map containing reserved keywords that are also operators. + * List of allowed reserved keywords in conditions. * * @var array */ - public static $OPERATORS = array( + public static $ALLOWED_KEYWORDS = array( 'AND' => 1, 'BETWEEN' => 1, 'EXISTS' => 1, + 'IF' => 1, 'IN' => 1, 'IS' => 1, 'LIKE' => 1, @@ -106,6 +107,7 @@ class Condition extends Component /** * Whether there was a `BETWEEN` keyword before or not. + * * It is required to keep track of them because their structure contains * the keyword `AND`, which is also an operator that delimits * expressions. @@ -115,6 +117,7 @@ class Condition extends Component $betweenBefore = false; for (; $list->idx < $list->count; ++$list->idx) { + /** * Token parsed at this moment. * @@ -142,11 +145,12 @@ class Condition extends Component // Conditions are delimited by logical operators. if (in_array($token->value, static::$DELIMITERS, true)) { if (($betweenBefore) && ($token->value === 'AND')) { + // The syntax of keyword `BETWEEN` is hard-coded. $betweenBefore = false; } else { + // The expression ended. $expr->expr = trim($expr->expr); if (!empty($expr->expr)) { - // Adding the condition that is delimited by this operator. $ret[] = $expr; } @@ -155,36 +159,39 @@ class Condition extends Component $expr->isOperator = true; $ret[] = $expr; + // Preparing to parse another condition. $expr = new Condition(); continue; } } - if ($token->type === Token::TYPE_OPERATOR) { - if ($token->value === '(') { - ++$brackets; - } elseif ($token->value === ')') { - --$brackets; - } - } - - // No keyword is expected. if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { if ($token->value === 'BETWEEN') { $betweenBefore = true; } - if (($brackets === 0) && (empty(static::$OPERATORS[$token->value]))) { + if (($brackets === 0) && (empty(static::$ALLOWED_KEYWORDS[$token->value]))) { break; } } + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + ++$brackets; + } elseif ($token->value === ')') { + --$brackets; + } + } + $expr->expr .= $token->token; if (($token->type === Token::TYPE_NONE) - || (($token->type === Token::TYPE_KEYWORD) && (!($token->flags & Token::FLAG_KEYWORD_RESERVED))) + || (($token->type === Token::TYPE_KEYWORD) + && (!($token->flags & Token::FLAG_KEYWORD_RESERVED))) || ($token->type === Token::TYPE_STRING) || ($token->type === Token::TYPE_SYMBOL) ) { - $expr->identifiers[] = $token->value; + if (!in_array($token->value, $expr->identifiers)) { + $expr->identifiers[] = $token->value; + } } } |