151 case '!': |
151 case '!': |
152 case '=': |
152 case '=': |
153 case '%': |
153 case '%': |
154 case '?': |
154 case '?': |
155 $end_operator = strspn( $str, self::OP_CHARS, $pos ); |
155 $end_operator = strspn( $str, self::OP_CHARS, $pos ); |
156 $operator = substr( $str, $pos, $end_operator ); |
156 $operator = substr( $str, $pos, $end_operator ); |
157 if ( ! array_key_exists( $operator, self::$op_precedence ) ) { |
157 if ( ! array_key_exists( $operator, self::$op_precedence ) ) { |
158 throw new Exception( sprintf( 'Unknown operator "%s"', $operator ) ); |
158 throw new Exception( sprintf( 'Unknown operator "%s"', $operator ) ); |
159 } |
159 } |
160 |
160 |
161 while ( ! empty( $stack ) ) { |
161 while ( ! empty( $stack ) ) { |
202 break; |
202 break; |
203 |
203 |
204 // Default - number or invalid |
204 // Default - number or invalid |
205 default: |
205 default: |
206 if ( $next >= '0' && $next <= '9' ) { |
206 if ( $next >= '0' && $next <= '9' ) { |
207 $span = strspn( $str, self::NUM_CHARS, $pos ); |
207 $span = strspn( $str, self::NUM_CHARS, $pos ); |
208 $output[] = array( 'value', intval( substr( $str, $pos, $span ) ) ); |
208 $output[] = array( 'value', intval( substr( $str, $pos, $span ) ) ); |
209 $pos += $span; |
209 $pos += $span; |
210 continue; |
210 break; |
211 } |
211 } |
212 |
212 |
213 throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); |
213 throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); |
214 } |
214 } |
215 } |
215 } |
251 * @param int $n Variable "n" to substitute. |
251 * @param int $n Variable "n" to substitute. |
252 * @return int Plural form value. |
252 * @return int Plural form value. |
253 */ |
253 */ |
254 public function execute( $n ) { |
254 public function execute( $n ) { |
255 $stack = array(); |
255 $stack = array(); |
256 $i = 0; |
256 $i = 0; |
257 $total = count( $this->tokens ); |
257 $total = count( $this->tokens ); |
258 while ( $i < $total ) { |
258 while ( $i < $total ) { |
259 $next = $this->tokens[$i]; |
259 $next = $this->tokens[ $i ]; |
260 $i++; |
260 $i++; |
261 if ( $next[0] === 'var' ) { |
261 if ( $next[0] === 'var' ) { |
262 $stack[] = $n; |
262 $stack[] = $n; |
263 continue; |
263 continue; |
264 } elseif ( $next[0] === 'value' ) { |
264 } elseif ( $next[0] === 'value' ) { |
267 } |
267 } |
268 |
268 |
269 // Only operators left. |
269 // Only operators left. |
270 switch ( $next[1] ) { |
270 switch ( $next[1] ) { |
271 case '%': |
271 case '%': |
272 $v2 = array_pop( $stack ); |
272 $v2 = array_pop( $stack ); |
273 $v1 = array_pop( $stack ); |
273 $v1 = array_pop( $stack ); |
274 $stack[] = $v1 % $v2; |
274 $stack[] = $v1 % $v2; |
275 break; |
275 break; |
276 |
276 |
277 case '||': |
277 case '||': |
278 $v2 = array_pop( $stack ); |
278 $v2 = array_pop( $stack ); |
279 $v1 = array_pop( $stack ); |
279 $v1 = array_pop( $stack ); |
280 $stack[] = $v1 || $v2; |
280 $stack[] = $v1 || $v2; |
281 break; |
281 break; |
282 |
282 |
283 case '&&': |
283 case '&&': |
284 $v2 = array_pop( $stack ); |
284 $v2 = array_pop( $stack ); |
285 $v1 = array_pop( $stack ); |
285 $v1 = array_pop( $stack ); |
286 $stack[] = $v1 && $v2; |
286 $stack[] = $v1 && $v2; |
287 break; |
287 break; |
288 |
288 |
289 case '<': |
289 case '<': |
290 $v2 = array_pop( $stack ); |
290 $v2 = array_pop( $stack ); |
291 $v1 = array_pop( $stack ); |
291 $v1 = array_pop( $stack ); |
292 $stack[] = $v1 < $v2; |
292 $stack[] = $v1 < $v2; |
293 break; |
293 break; |
294 |
294 |
295 case '<=': |
295 case '<=': |
296 $v2 = array_pop( $stack ); |
296 $v2 = array_pop( $stack ); |
297 $v1 = array_pop( $stack ); |
297 $v1 = array_pop( $stack ); |
298 $stack[] = $v1 <= $v2; |
298 $stack[] = $v1 <= $v2; |
299 break; |
299 break; |
300 |
300 |
301 case '>': |
301 case '>': |
302 $v2 = array_pop( $stack ); |
302 $v2 = array_pop( $stack ); |
303 $v1 = array_pop( $stack ); |
303 $v1 = array_pop( $stack ); |
304 $stack[] = $v1 > $v2; |
304 $stack[] = $v1 > $v2; |
305 break; |
305 break; |
306 |
306 |
307 case '>=': |
307 case '>=': |
308 $v2 = array_pop( $stack ); |
308 $v2 = array_pop( $stack ); |
309 $v1 = array_pop( $stack ); |
309 $v1 = array_pop( $stack ); |
310 $stack[] = $v1 >= $v2; |
310 $stack[] = $v1 >= $v2; |
311 break; |
311 break; |
312 |
312 |
313 case '!=': |
313 case '!=': |
314 $v2 = array_pop( $stack ); |
314 $v2 = array_pop( $stack ); |
315 $v1 = array_pop( $stack ); |
315 $v1 = array_pop( $stack ); |
316 $stack[] = $v1 != $v2; |
316 $stack[] = $v1 != $v2; |
317 break; |
317 break; |
318 |
318 |
319 case '==': |
319 case '==': |
320 $v2 = array_pop( $stack ); |
320 $v2 = array_pop( $stack ); |
321 $v1 = array_pop( $stack ); |
321 $v1 = array_pop( $stack ); |
322 $stack[] = $v1 == $v2; |
322 $stack[] = $v1 == $v2; |
323 break; |
323 break; |
324 |
324 |
325 case '?:': |
325 case '?:': |
326 $v3 = array_pop( $stack ); |
326 $v3 = array_pop( $stack ); |
327 $v2 = array_pop( $stack ); |
327 $v2 = array_pop( $stack ); |
328 $v1 = array_pop( $stack ); |
328 $v1 = array_pop( $stack ); |
329 $stack[] = $v1 ? $v2 : $v3; |
329 $stack[] = $v1 ? $v2 : $v3; |
330 break; |
330 break; |
331 |
331 |
332 default: |
332 default: |
333 throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); |
333 throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); |