diff options
author | Deven Bansod <devenbansod.bits@gmail.com> | 2016-10-21 12:13:12 +0530 |
---|---|---|
committer | Deven Bansod <devenbansod.bits@gmail.com> | 2016-10-21 12:21:51 +0530 |
commit | a54adc82d185722d36a0d1350c3ce80298aa15a4 (patch) | |
tree | 9d283d311de7d7a24747d2c86fbc8167bdc4d226 /src | |
parent | 06f7d5232581c3a0afd84cf54a549a0b79355adc (diff) | |
download | sql-parser-a54adc82d185722d36a0d1350c3ce80298aa15a4.zip sql-parser-a54adc82d185722d36a0d1350c3ce80298aa15a4.tar.gz sql-parser-a54adc82d185722d36a0d1350c3ce80298aa15a4.tar.bz2 |
Enable Lexing of begin_label in the in-procedure statements
Ex. BEGIN.. END, LOOP, REPEAT, WHILE statements
Fix #57
Fix phpmyadmin/phpmyadmin#12344
Fix phpmyadmin/phpmyadmin#12228
Signed-off-by: Deven Bansod <devenbansod.bits@gmail.com>
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. |