wp/wp-includes/pomo/plural-forms.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    32 	 *
    32 	 *
    33 	 * @since 4.9.0
    33 	 * @since 4.9.0
    34 	 * @var array $op_precedence Operator precedence from highest to lowest.
    34 	 * @var array $op_precedence Operator precedence from highest to lowest.
    35 	 */
    35 	 */
    36 	protected static $op_precedence = array(
    36 	protected static $op_precedence = array(
    37 		'%' => 6,
    37 		'%'  => 6,
    38 
    38 
    39 		'<' => 5,
    39 		'<'  => 5,
    40 		'<=' => 5,
    40 		'<=' => 5,
    41 		'>' => 5,
    41 		'>'  => 5,
    42 		'>=' => 5,
    42 		'>=' => 5,
    43 
    43 
    44 		'==' => 4,
    44 		'==' => 4,
    45 		'!=' => 4,
    45 		'!=' => 4,
    46 
    46 
    47 		'&&' => 3,
    47 		'&&' => 3,
    48 
    48 
    49 		'||' => 2,
    49 		'||' => 2,
    50 
    50 
    51 		'?:' => 1,
    51 		'?:' => 1,
    52 		'?' => 1,
    52 		'?'  => 1,
    53 
    53 
    54 		'(' => 0,
    54 		'('  => 0,
    55 		')' => 0,
    55 		')'  => 0,
    56 	);
    56 	);
    57 
    57 
    58 	/**
    58 	/**
    59 	 * Tokens generated from the string.
    59 	 * Tokens generated from the string.
    60 	 *
    60 	 *
    96 		$pos = 0;
    96 		$pos = 0;
    97 		$len = strlen( $str );
    97 		$len = strlen( $str );
    98 
    98 
    99 		// Convert infix operators to postfix using the shunting-yard algorithm.
    99 		// Convert infix operators to postfix using the shunting-yard algorithm.
   100 		$output = array();
   100 		$output = array();
   101 		$stack = array();
   101 		$stack  = array();
   102 		while ( $pos < $len ) {
   102 		while ( $pos < $len ) {
   103 			$next = substr( $str, $pos, 1 );
   103 			$next = substr( $str, $pos, 1 );
   104 
   104 
   105 			switch ( $next ) {
   105 			switch ( $next ) {
   106 				// Ignore whitespace
   106 				// Ignore whitespace
   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 ) ) {
   189 							continue;
   189 							continue;
   190 						}
   190 						}
   191 
   191 
   192 						// Replace.
   192 						// Replace.
   193 						$stack[ $s_pos ] = '?:';
   193 						$stack[ $s_pos ] = '?:';
   194 						$found = true;
   194 						$found           = true;
   195 						break;
   195 						break;
   196 					}
   196 					}
   197 
   197 
   198 					if ( ! $found ) {
   198 					if ( ! $found ) {
   199 						throw new Exception( 'Missing starting "?" ternary operator' );
   199 						throw new Exception( 'Missing starting "?" ternary operator' );
   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] ) );