diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Context.php | 10 | ||||
-rw-r--r-- | src/Lexer.php | 57 | ||||
-rw-r--r-- | src/Token.php | 12 |
3 files changed, 78 insertions, 1 deletions
diff --git a/src/Context.php b/src/Context.php index 0bdc696..3685857 100644 --- a/src/Context.php +++ b/src/Context.php @@ -30,6 +30,16 @@ abstract class Context const KEYWORD_MAX_LENGTH = 30; /** + * The maximum length of a label. + * + * @see static::$TOKEN_LABEL + * Ref: https://dev.mysql.com/doc/refman/5.7/en/statement-labels.html + * + * @var int + */ + const LABEL_MAX_LENGTH = 16; + + /** * The maximum length of an operator. * * @see static::$TOKEN_OPERATOR diff --git a/src/Lexer.php b/src/Lexer.php index 7fb2356..9de2a7a 100644 --- a/src/Lexer.php +++ b/src/Lexer.php @@ -76,7 +76,7 @@ class Lexer 'parseDelimiter', 'parseWhitespace', 'parseNumber', 'parseComment', 'parseOperator', 'parseBool', 'parseString', - 'parseSymbol', 'parseKeyword', 'parseUnknown' + 'parseSymbol', 'parseKeyword', 'parseLabel', 'parseUnknown' ); /** @@ -442,6 +442,61 @@ class Lexer } /** + * Parses a label. + * + * @return Token + */ + public function parseLabel() + { + $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::LABEL_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; + } + } elseif ($this->str[$this->last] === ':') { + $token .= $this->str[$this->last]; + $ret = new Token($token, Token::TYPE_LABEL); + $iEnd = $this->last; + break; + } else { + $lastSpace = false; + } + $token .= $this->str[$this->last]; + } + + $this->last = $iEnd; + return $ret; + } + + /** * Parses an operator. * * @return Token diff --git a/src/Token.php b/src/Token.php index 3181a44..e5001ef 100644 --- a/src/Token.php +++ b/src/Token.php @@ -119,6 +119,18 @@ class Token */ const TYPE_DELIMITER = 9; + /** + * Labels in LOOP statement, ITERATE statement etc. + * For example (only for begin label): + * begin_label: BEGIN [statement_list] END [end_label] + * begin_label: LOOP [statement_list] END LOOP [end_label] + * begin_label: REPEAT [statement_list] ... END REPEAT [end_label] + * begin_label: WHILE ... DO [statement_list] END WHILE [end_label] + * + * @var int + */ + const TYPE_LABEL = 10; + // Flags that describe the tokens in more detail. // All keywords must have flag 1 so `Context::isKeyword` method doesn't // require strict comparison. |