Gets the next token.
public getNextOfType ( integer $type ) : |
||
$type | integer | The type. |
return |
public function testGetNextOfType() { $list = new TokensList($this->tokens); $this->assertEquals($this->tokens[0], $list->getNextOfType(Token::TYPE_KEYWORD)); $this->assertEquals($this->tokens[4], $list->getNextOfType(Token::TYPE_KEYWORD)); $this->assertEquals(null, $list->getNextOfType(Token::TYPE_KEYWORD)); }
/** * Jump to the end of the delimiter. * * @param Parser $parser The instance that requests parsing. * @param TokensList $list The list of tokens to be parsed. * @param Token $token The token that is being parsed. * * @return void */ public function after(Parser $parser, TokensList $list, Token $token) { $list->getNextOfType(Token::TYPE_DELIMITER); --$list->idx; }
/** * Parses the statements defined by the tokens list. * * @param Parser $parser The instance that requests parsing. * @param TokensList $list The list of tokens to be parsed. * * @return void */ public function parse(Parser $parser, TokensList $list) { /** * Array containing all list of clauses parsed. * This is used to check for duplicates. * * @var array $parsedClauses */ $parsedClauses = array(); // This may be corrected by the parser. $this->first = $list->idx; /** * Whether options were parsed or not. * For statements that do not have any options this is set to `true` by * default. * * @var bool $parsedOptions */ $parsedOptions = empty(static::$OPTIONS); for (; $list->idx < $list->count; ++$list->idx) { /** * Token parsed at this moment. * * @var Token $token */ $token = $list->tokens[$list->idx]; // End of statement. if ($token->type === Token::TYPE_DELIMITER) { break; } // Checking if this closing bracket is the pair for a bracket // outside the statement. if ($token->value === ')' && $parser->brackets > 0) { --$parser->brackets; continue; } // Only keywords are relevant here. Other parts of the query are // processed in the functions below. if ($token->type !== Token::TYPE_KEYWORD) { if ($token->type !== TOKEN::TYPE_COMMENT && $token->type !== Token::TYPE_WHITESPACE) { $parser->error(__('Unexpected token.'), $token); } continue; } // Unions are parsed by the parser because they represent more than // one statement. if ($token->value === 'UNION' || $token->value === 'UNION ALL' || $token->value === 'UNION DISTINCT') { break; } $lastIdx = $list->idx; // ON DUPLICATE KEY UPDATE ... // has to be parsed in parent statement (INSERT or REPLACE) // so look for it and break if (get_class($this) === 'SqlParser\\Statements\\SelectStatement' && $token->value === 'ON') { ++$list->idx; // Skip ON // look for ON DUPLICATE KEY UPDATE $first = $list->getNextOfType(Token::TYPE_KEYWORD); $second = $list->getNextOfType(Token::TYPE_KEYWORD); $third = $list->getNextOfType(Token::TYPE_KEYWORD); if ($first && $second && $third && $first->value === 'DUPLICATE' && $second->value === 'KEY' && $third->value === 'UPDATE') { $list->idx = $lastIdx; break; } } $list->idx = $lastIdx; /** * The name of the class that is used for parsing. * * @var Component $class */ $class = null; /** * The name of the field where the result of the parsing is stored. * * @var string $field */ $field = null; /** * Parser's options. * * @var array $options */ $options = array(); // Looking for duplicated clauses. if (!empty(Parser::$KEYWORD_PARSERS[$token->value]) || !empty(Parser::$STATEMENT_PARSERS[$token->value])) { if (!empty($parsedClauses[$token->value])) { $parser->error(__('This type of clause was previously parsed.'), $token); break; } $parsedClauses[$token->value] = true; } // Checking if this is the beginning of a clause. if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) { $class = Parser::$KEYWORD_PARSERS[$token->value]['class']; $field = Parser::$KEYWORD_PARSERS[$token->value]['field']; if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) { $options = Parser::$KEYWORD_PARSERS[$token->value]['options']; } } // Checking if this is the beginning of the statement. if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) { if (!empty(static::$CLAUSES) && empty(static::$CLAUSES[$token->value])) { // Some keywords (e.g. `SET`) may be the beginning of a // statement and a clause. // If such keyword was found and it cannot be a clause of // this statement it means it is a new statement, but no // delimiter was found between them. $parser->error(__('A new statement was found, but no delimiter between it and the previous one.'), $token); break; } if (!$parsedOptions) { if (empty(static::$OPTIONS[$token->value])) { // Skipping keyword because if it is not a option. ++$list->idx; } $this->options = OptionsArray::parse($parser, $list, static::$OPTIONS); $parsedOptions = true; } } elseif ($class === null) { // There is no parser for this keyword and isn't the beginning // of a statement (so no options) either. $parser->error(__('Unrecognized keyword.'), $token); continue; } $this->before($parser, $list, $token); // Parsing this keyword. if ($class !== null) { ++$list->idx; // Skipping keyword or last option. $this->{$field} = $class::parse($parser, $list, $options); } $this->after($parser, $list, $token); } // This may be corrected by the parser. $this->last = --$list->idx; // Go back to last used token. }