diff --git a/wp-includes/pomo/plural-forms.php b/wp-includes/pomo/plural-forms.php index f25a84188d..73477b454b 100644 --- a/wp-includes/pomo/plural-forms.php +++ b/wp-includes/pomo/plural-forms.php @@ -5,340 +5,342 @@ * * @since 4.9.0 */ -class Plural_Forms { - /** - * Operator characters. - * - * @since 4.9.0 - * @var string OP_CHARS Operator characters. - */ - const OP_CHARS = '|&> 6, + /** + * Operator precedence. + * + * Operator precedence from highest to lowest. Higher numbers indicate + * higher precedence, and are executed first. + * + * @see https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence + * + * @since 4.9.0 + * @var array $op_precedence Operator precedence from highest to lowest. + */ + protected static $op_precedence = array( + '%' => 6, - '<' => 5, - '<=' => 5, - '>' => 5, - '>=' => 5, + '<' => 5, + '<=' => 5, + '>' => 5, + '>=' => 5, - '==' => 4, - '!=' => 4, + '==' => 4, + '!=' => 4, - '&&' => 3, + '&&' => 3, - '||' => 2, + '||' => 2, - '?:' => 1, - '?' => 1, + '?:' => 1, + '?' => 1, - '(' => 0, - ')' => 0, - ); + '(' => 0, + ')' => 0, + ); - /** - * Tokens generated from the string. - * - * @since 4.9.0 - * @var array $tokens List of tokens. - */ - protected $tokens = array(); + /** + * Tokens generated from the string. + * + * @since 4.9.0 + * @var array $tokens List of tokens. + */ + protected $tokens = array(); - /** - * Cache for repeated calls to the function. - * - * @since 4.9.0 - * @var array $cache Map of $n => $result - */ - protected $cache = array(); + /** + * Cache for repeated calls to the function. + * + * @since 4.9.0 + * @var array $cache Map of $n => $result + */ + protected $cache = array(); - /** - * Constructor. - * - * @since 4.9.0 - * - * @param string $str Plural function (just the bit after `plural=` from Plural-Forms) - */ - public function __construct( $str ) { - $this->parse( $str ); - } + /** + * Constructor. + * + * @since 4.9.0 + * + * @param string $str Plural function (just the bit after `plural=` from Plural-Forms) + */ + public function __construct( $str ) { + $this->parse( $str ); + } - /** - * Parse a Plural-Forms string into tokens. - * - * Uses the shunting-yard algorithm to convert the string to Reverse Polish - * Notation tokens. - * - * @since 4.9.0 - * - * @param string $str String to parse. - */ - protected function parse( $str ) { - $pos = 0; - $len = strlen( $str ); + /** + * Parse a Plural-Forms string into tokens. + * + * Uses the shunting-yard algorithm to convert the string to Reverse Polish + * Notation tokens. + * + * @since 4.9.0 + * + * @param string $str String to parse. + */ + protected function parse( $str ) { + $pos = 0; + $len = strlen( $str ); - // Convert infix operators to postfix using the shunting-yard algorithm. - $output = array(); - $stack = array(); - while ( $pos < $len ) { - $next = substr( $str, $pos, 1 ); + // Convert infix operators to postfix using the shunting-yard algorithm. + $output = array(); + $stack = array(); + while ( $pos < $len ) { + $next = substr( $str, $pos, 1 ); - switch ( $next ) { - // Ignore whitespace. - case ' ': - case "\t": - $pos++; - break; - - // Variable (n). - case 'n': - $output[] = array( 'var' ); - $pos++; - break; - - // Parentheses. - case '(': - $stack[] = $next; - $pos++; - break; - - case ')': - $found = false; - while ( ! empty( $stack ) ) { - $o2 = $stack[ count( $stack ) - 1 ]; - if ( '(' !== $o2 ) { - $output[] = array( 'op', array_pop( $stack ) ); - continue; - } - - // Discard open paren. - array_pop( $stack ); - $found = true; + switch ( $next ) { + // Ignore whitespace. + case ' ': + case "\t": + $pos++; break; - } - if ( ! $found ) { - throw new Exception( 'Mismatched parentheses' ); - } + // Variable (n). + case 'n': + $output[] = array( 'var' ); + $pos++; + break; - $pos++; - break; + // Parentheses. + case '(': + $stack[] = $next; + $pos++; + break; - // Operators. - case '|': - case '&': - case '>': - case '<': - case '!': - case '=': - case '%': - case '?': - $end_operator = strspn( $str, self::OP_CHARS, $pos ); - $operator = substr( $str, $pos, $end_operator ); - if ( ! array_key_exists( $operator, self::$op_precedence ) ) { - throw new Exception( sprintf( 'Unknown operator "%s"', $operator ) ); - } - - while ( ! empty( $stack ) ) { - $o2 = $stack[ count( $stack ) - 1 ]; - - // Ternary is right-associative in C. - if ( '?:' === $operator || '?' === $operator ) { - if ( self::$op_precedence[ $operator ] >= self::$op_precedence[ $o2 ] ) { - break; + case ')': + $found = false; + while ( ! empty( $stack ) ) { + $o2 = $stack[ count( $stack ) - 1 ]; + if ( '(' !== $o2 ) { + $output[] = array( 'op', array_pop( $stack ) ); + continue; } - } elseif ( self::$op_precedence[ $operator ] > self::$op_precedence[ $o2 ] ) { + + // Discard open paren. + array_pop( $stack ); + $found = true; break; } - $output[] = array( 'op', array_pop( $stack ) ); - } - $stack[] = $operator; - - $pos += $end_operator; - break; - - // Ternary "else". - case ':': - $found = false; - $s_pos = count( $stack ) - 1; - while ( $s_pos >= 0 ) { - $o2 = $stack[ $s_pos ]; - if ( '?' !== $o2 ) { - $output[] = array( 'op', array_pop( $stack ) ); - $s_pos--; - continue; + if ( ! $found ) { + throw new Exception( 'Mismatched parentheses' ); } - // Replace. - $stack[ $s_pos ] = '?:'; - $found = true; + $pos++; break; - } - if ( ! $found ) { - throw new Exception( 'Missing starting "?" ternary operator' ); - } - $pos++; - break; + // Operators. + case '|': + case '&': + case '>': + case '<': + case '!': + case '=': + case '%': + case '?': + $end_operator = strspn( $str, self::OP_CHARS, $pos ); + $operator = substr( $str, $pos, $end_operator ); + if ( ! array_key_exists( $operator, self::$op_precedence ) ) { + throw new Exception( sprintf( 'Unknown operator "%s"', $operator ) ); + } - // Default - number or invalid. - default: - if ( $next >= '0' && $next <= '9' ) { - $span = strspn( $str, self::NUM_CHARS, $pos ); - $output[] = array( 'value', intval( substr( $str, $pos, $span ) ) ); - $pos += $span; + while ( ! empty( $stack ) ) { + $o2 = $stack[ count( $stack ) - 1 ]; + + // Ternary is right-associative in C. + if ( '?:' === $operator || '?' === $operator ) { + if ( self::$op_precedence[ $operator ] >= self::$op_precedence[ $o2 ] ) { + break; + } + } elseif ( self::$op_precedence[ $operator ] > self::$op_precedence[ $o2 ] ) { + break; + } + + $output[] = array( 'op', array_pop( $stack ) ); + } + $stack[] = $operator; + + $pos += $end_operator; break; - } - throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); - } - } + // Ternary "else". + case ':': + $found = false; + $s_pos = count( $stack ) - 1; + while ( $s_pos >= 0 ) { + $o2 = $stack[ $s_pos ]; + if ( '?' !== $o2 ) { + $output[] = array( 'op', array_pop( $stack ) ); + $s_pos--; + continue; + } - while ( ! empty( $stack ) ) { - $o2 = array_pop( $stack ); - if ( '(' === $o2 || ')' === $o2 ) { - throw new Exception( 'Mismatched parentheses' ); + // Replace. + $stack[ $s_pos ] = '?:'; + $found = true; + break; + } + + if ( ! $found ) { + throw new Exception( 'Missing starting "?" ternary operator' ); + } + $pos++; + break; + + // Default - number or invalid. + default: + if ( $next >= '0' && $next <= '9' ) { + $span = strspn( $str, self::NUM_CHARS, $pos ); + $output[] = array( 'value', intval( substr( $str, $pos, $span ) ) ); + $pos += $span; + break; + } + + throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); + } } - $output[] = array( 'op', $o2 ); + while ( ! empty( $stack ) ) { + $o2 = array_pop( $stack ); + if ( '(' === $o2 || ')' === $o2 ) { + throw new Exception( 'Mismatched parentheses' ); + } + + $output[] = array( 'op', $o2 ); + } + + $this->tokens = $output; } - $this->tokens = $output; - } - - /** - * Get the plural form for a number. - * - * Caches the value for repeated calls. - * - * @since 4.9.0 - * - * @param int $num Number to get plural form for. - * @return int Plural form value. - */ - public function get( $num ) { - if ( isset( $this->cache[ $num ] ) ) { + /** + * Get the plural form for a number. + * + * Caches the value for repeated calls. + * + * @since 4.9.0 + * + * @param int $num Number to get plural form for. + * @return int Plural form value. + */ + public function get( $num ) { + if ( isset( $this->cache[ $num ] ) ) { + return $this->cache[ $num ]; + } + $this->cache[ $num ] = $this->execute( $num ); return $this->cache[ $num ]; } - $this->cache[ $num ] = $this->execute( $num ); - return $this->cache[ $num ]; - } - /** - * Execute the plural form function. - * - * @since 4.9.0 - * - * @param int $n Variable "n" to substitute. - * @return int Plural form value. - */ - public function execute( $n ) { - $stack = array(); - $i = 0; - $total = count( $this->tokens ); - while ( $i < $total ) { - $next = $this->tokens[ $i ]; - $i++; - if ( 'var' === $next[0] ) { - $stack[] = $n; - continue; - } elseif ( 'value' === $next[0] ) { - $stack[] = $next[1]; - continue; + /** + * Execute the plural form function. + * + * @since 4.9.0 + * + * @param int $n Variable "n" to substitute. + * @return int Plural form value. + */ + public function execute( $n ) { + $stack = array(); + $i = 0; + $total = count( $this->tokens ); + while ( $i < $total ) { + $next = $this->tokens[ $i ]; + $i++; + if ( 'var' === $next[0] ) { + $stack[] = $n; + continue; + } elseif ( 'value' === $next[0] ) { + $stack[] = $next[1]; + continue; + } + + // Only operators left. + switch ( $next[1] ) { + case '%': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 % $v2; + break; + + case '||': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 || $v2; + break; + + case '&&': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 && $v2; + break; + + case '<': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 < $v2; + break; + + case '<=': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 <= $v2; + break; + + case '>': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 > $v2; + break; + + case '>=': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 >= $v2; + break; + + case '!=': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 != $v2; + break; + + case '==': + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 == $v2; + break; + + case '?:': + $v3 = array_pop( $stack ); + $v2 = array_pop( $stack ); + $v1 = array_pop( $stack ); + $stack[] = $v1 ? $v2 : $v3; + break; + + default: + throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); + } } - // Only operators left. - switch ( $next[1] ) { - case '%': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 % $v2; - break; - - case '||': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 || $v2; - break; - - case '&&': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 && $v2; - break; - - case '<': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 < $v2; - break; - - case '<=': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 <= $v2; - break; - - case '>': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 > $v2; - break; - - case '>=': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 >= $v2; - break; - - case '!=': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 != $v2; - break; - - case '==': - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 == $v2; - break; - - case '?:': - $v3 = array_pop( $stack ); - $v2 = array_pop( $stack ); - $v1 = array_pop( $stack ); - $stack[] = $v1 ? $v2 : $v3; - break; - - default: - throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); + if ( count( $stack ) !== 1 ) { + throw new Exception( 'Too many values remaining on the stack' ); } - } - if ( count( $stack ) !== 1 ) { - throw new Exception( 'Too many values remaining on the stack' ); + return (int) $stack[0]; } - - return (int) $stack[0]; } -} +endif; diff --git a/wp-includes/version.php b/wp-includes/version.php index c928cb1902..48c4e55ccd 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.6-alpha-48767'; +$wp_version = '5.6-alpha-48769'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.