1<?php 2 3/** 4 * `VALUES` keyword parser. 5 */ 6 7namespace PhpMyAdmin\SqlParser\Components; 8 9use PhpMyAdmin\SqlParser\Component; 10use PhpMyAdmin\SqlParser\Parser; 11use PhpMyAdmin\SqlParser\Token; 12use PhpMyAdmin\SqlParser\TokensList; 13use PhpMyAdmin\SqlParser\Translator; 14 15/** 16 * `VALUES` keyword parser. 17 * 18 * @category Keywords 19 * 20 * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+ 21 */ 22class Array2d extends Component 23{ 24 /** 25 * @param Parser $parser the parser that serves as context 26 * @param TokensList $list the list of tokens that are being parsed 27 * @param array $options parameters for parsing 28 * 29 * @return ArrayObj[] 30 */ 31 public static function parse(Parser $parser, TokensList $list, array $options = array()) 32 { 33 $ret = array(); 34 35 /** 36 * The number of values in each set. 37 * 38 * @var int 39 */ 40 $count = -1; 41 42 /** 43 * The state of the parser. 44 * 45 * Below are the states of the parser. 46 * 47 * 0 ----------------------[ array ]----------------------> 1 48 * 49 * 1 ------------------------[ , ]------------------------> 0 50 * 1 -----------------------[ else ]----------------------> (END) 51 * 52 * @var int 53 */ 54 $state = 0; 55 56 for (; $list->idx < $list->count; ++$list->idx) { 57 /** 58 * Token parsed at this moment. 59 * 60 * @var Token 61 */ 62 $token = $list->tokens[$list->idx]; 63 64 // End of statement. 65 if ($token->type === Token::TYPE_DELIMITER) { 66 break; 67 } 68 69 // Skipping whitespaces and comments. 70 if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { 71 continue; 72 } 73 74 // No keyword is expected. 75 if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { 76 break; 77 } 78 79 if ($state === 0) { 80 if ($token->value === '(') { 81 $arr = ArrayObj::parse($parser, $list, $options); 82 $arrCount = count($arr->values); 83 if ($count === -1) { 84 $count = $arrCount; 85 } elseif ($arrCount !== $count) { 86 $parser->error( 87 sprintf( 88 Translator::gettext('%1$d values were expected, but found %2$d.'), 89 $count, 90 $arrCount 91 ), 92 $token 93 ); 94 } 95 $ret[] = $arr; 96 $state = 1; 97 } else { 98 break; 99 } 100 } elseif ($state === 1) { 101 if ($token->value === ',') { 102 $state = 0; 103 } else { 104 break; 105 } 106 } 107 } 108 109 if ($state === 0) { 110 $parser->error( 111 'An opening bracket followed by a set of values was expected.', 112 $list->tokens[$list->idx] 113 ); 114 } 115 116 --$list->idx; 117 118 return $ret; 119 } 120 121 /** 122 * @param ArrayObj[] $component the component to be built 123 * @param array $options parameters for building 124 * 125 * @return string 126 */ 127 public static function build($component, array $options = array()) 128 { 129 return ArrayObj::build($component); 130 } 131} 132