@@ -30,17 +30,18 @@ class Condition extends Component
3030 *
3131 * @var array
3232 */
33- public static $ DELIMITERS = array ('&& ' , 'AND ' , 'OR ' , 'XOR ' , '|| ' );
33+ public static $ DELIMITERS = array ('&& ' , '|| ' , 'AND ' , 'OR ' , 'XOR ' );
3434
3535 /**
36- * Hash map containing reserved keywords that are also operators .
36+ * List of allowed reserved keywords in conditions .
3737 *
3838 * @var array
3939 */
40- public static $ OPERATORS = array (
40+ public static $ ALLOWED_KEYWORDS = array (
4141 'AND ' => 1 ,
4242 'BETWEEN ' => 1 ,
4343 'EXISTS ' => 1 ,
44+ 'IF ' => 1 ,
4445 'IN ' => 1 ,
4546 'IS ' => 1 ,
4647 'LIKE ' => 1 ,
@@ -106,6 +107,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
106107
107108 /**
108109 * Whether there was a `BETWEEN` keyword before or not.
110+ *
109111 * It is required to keep track of them because their structure contains
110112 * the keyword `AND`, which is also an operator that delimits
111113 * expressions.
@@ -115,6 +117,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
115117 $ betweenBefore = false ;
116118
117119 for (; $ list ->idx < $ list ->count ; ++$ list ->idx ) {
120+
118121 /**
119122 * Token parsed at this moment.
120123 *
@@ -142,11 +145,12 @@ public static function parse(Parser $parser, TokensList $list, array $options =
142145 // Conditions are delimited by logical operators.
143146 if (in_array ($ token ->value , static ::$ DELIMITERS , true )) {
144147 if (($ betweenBefore ) && ($ token ->value === 'AND ' )) {
148+ // The syntax of keyword `BETWEEN` is hard-coded.
145149 $ betweenBefore = false ;
146150 } else {
151+ // The expression ended.
147152 $ expr ->expr = trim ($ expr ->expr );
148153 if (!empty ($ expr ->expr )) {
149- // Adding the condition that is delimited by this operator.
150154 $ ret [] = $ expr ;
151155 }
152156
@@ -155,36 +159,39 @@ public static function parse(Parser $parser, TokensList $list, array $options =
155159 $ expr ->isOperator = true ;
156160 $ ret [] = $ expr ;
157161
162+ // Preparing to parse another condition.
158163 $ expr = new Condition ();
159164 continue ;
160165 }
161166 }
162167
163- if ($ token ->type === Token::TYPE_OPERATOR ) {
164- if ($ token ->value === '( ' ) {
165- ++$ brackets ;
166- } elseif ($ token ->value === ') ' ) {
167- --$ brackets ;
168- }
169- }
170-
171- // No keyword is expected.
172168 if (($ token ->type === Token::TYPE_KEYWORD ) && ($ token ->flags & Token::FLAG_KEYWORD_RESERVED )) {
173169 if ($ token ->value === 'BETWEEN ' ) {
174170 $ betweenBefore = true ;
175171 }
176- if (($ brackets === 0 ) && (empty (static ::$ OPERATORS [$ token ->value ]))) {
172+ if (($ brackets === 0 ) && (empty (static ::$ ALLOWED_KEYWORDS [$ token ->value ]))) {
177173 break ;
178174 }
179175 }
180176
177+ if ($ token ->type === Token::TYPE_OPERATOR ) {
178+ if ($ token ->value === '( ' ) {
179+ ++$ brackets ;
180+ } elseif ($ token ->value === ') ' ) {
181+ --$ brackets ;
182+ }
183+ }
184+
181185 $ expr ->expr .= $ token ->token ;
182186 if (($ token ->type === Token::TYPE_NONE )
183- || (($ token ->type === Token::TYPE_KEYWORD ) && (!($ token ->flags & Token::FLAG_KEYWORD_RESERVED )))
187+ || (($ token ->type === Token::TYPE_KEYWORD )
188+ && (!($ token ->flags & Token::FLAG_KEYWORD_RESERVED )))
184189 || ($ token ->type === Token::TYPE_STRING )
185190 || ($ token ->type === Token::TYPE_SYMBOL )
186191 ) {
187- $ expr ->identifiers [] = $ token ->value ;
192+ if (!in_array ($ token ->value , $ expr ->identifiers )) {
193+ $ expr ->identifiers [] = $ token ->value ;
194+ }
188195 }
189196 }
190197
0 commit comments