public function parseKeyword()
{
$token = '';
/**
* Value to be returned.
*
* @var Token $ret
*/
$ret = null;
/**
* The value of `$this->last` where `$token` ends in `$this->str`.
*
* @var int $iEnd
*/
$iEnd = $this->last;
/**
* Whether last parsed character is a whitespace.
*
* @var bool $lastSpace
*/
$lastSpace = false;
for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
// Composed keywords shouldn't have more than one whitespace between
// keywords.
if (Context::isWhitespace($this->str[$this->last])) {
if ($lastSpace) {
--$j;
// The size of the keyword didn't increase.
continue;
} else {
$lastSpace = true;
}
} else {
$lastSpace = false;
}
$token .= $this->str[$this->last];
if ($this->last + 1 === $this->len || Context::isSeparator($this->str[$this->last + 1])) {
if ($flags = Context::isKeyword($token)) {
$ret = new Token($token, Token::TYPE_KEYWORD, $flags);
$iEnd = $this->last;
// We don't break so we find longest keyword.
// For example, `OR` and `ORDER` have a common prefix `OR`.
// If we stopped at `OR`, the parsing would be invalid.
}
}
}
$this->last = $iEnd;
return $ret;
}