/**
* @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)
{
++$list->idx;
// Skipping `INSERT`.
// parse any options if provided
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
++$list->idx;
$token = $list->tokens[$list->idx];
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------------------------[ INTO ]----------------------------------> 1
*
* 1 -------------------------[ VALUES/VALUE/SET/SELECT ]-----------------------> 2
*
* 2 -------------------------[ ON DUPLICATE KEY UPDATE ]-----------------------> 3
*
* @var int $state
*/
$state = 0;
/**
* For keeping track of semi-states on encountering
* ON DUPLICATE KEY UPDATE ...
*
*/
$miniState = 0;
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;
}
// Skipping whitespaces and comments.
if ($token->type === Token::TYPE_WHITESPACE || $token->type === Token::TYPE_COMMENT) {
continue;
}
if ($state === 0) {
if ($token->type === Token::TYPE_KEYWORD && $token->value !== 'INTO') {
$parser->error(__('Unexpected keyword.'), $token);
break;
} else {
++$list->idx;
$this->into = IntoKeyword::parse($parser, $list);
}
$state = 1;
} elseif ($state === 1) {
if ($token->type === Token::TYPE_KEYWORD) {
if ($token->value === 'VALUE' || $token->value === 'VALUES') {
++$list->idx;
// skip VALUES
$this->values = Array2d::parse($parser, $list);
} elseif ($token->value === 'SET') {
++$list->idx;
// skip SET
$this->set = SetOperation::parse($parser, $list);
} elseif ($token->value === 'SELECT') {
$this->select = new SelectStatement($parser, $list);
} else {
$parser->error(__('Unexpected keyword.'), $token);
break;
}
$state = 2;
$miniState = 1;
} else {
$parser->error(__('Unexpected token.'), $token);
break;
}
} elseif ($state == 2) {
$lastCount = $miniState;
if ($miniState === 1 && $token->value === 'ON') {
$miniState++;
} elseif ($miniState === 2 && $token->value === 'DUPLICATE') {
$miniState++;
} elseif ($miniState === 3 && $token->value === 'KEY') {
$miniState++;
} elseif ($miniState === 4 && $token->value === 'UPDATE') {
$miniState++;
}
if ($lastCount === $miniState) {
$parser->error(__('Unexpected token.'), $token);
break;
}
if ($miniState === 5) {
++$list->idx;
$this->onDuplicateSet = SetOperation::parse($parser, $list);
$state = 3;
}
}
}
--$list->idx;
}