SqlParser\Components\CreateDefinition::parse PHP Method

parse() public static method

public static parse ( Parser $parser, TokensList $list, array $options = [] ) : CreateDefinition[]
$parser SqlParser\Parser The parser that serves as context.
$list SqlParser\TokensList The list of tokens that are being parsed.
$options array Parameters for parsing.
return CreateDefinition[]
    public static function parse(Parser $parser, TokensList $list, array $options = array())
    {
        $ret = array();
        $expr = new CreateDefinition();
        /**
         * The state of the parser.
         *
         * Below are the states of the parser.
         *
         *      0 -----------------------[ ( ]------------------------> 1
         *
         *      1 --------------------[ CONSTRAINT ]------------------> 1
         *      1 -----------------------[ key ]----------------------> 2
         *      1 -------------[ constraint / column name ]-----------> 2
         *
         *      2 --------------------[ data type ]-------------------> 3
         *
         *      3 ---------------------[ options ]--------------------> 4
         *
         *      4 --------------------[ REFERENCES ]------------------> 4
         *
         *      5 ------------------------[ , ]-----------------------> 1
         *      5 ------------------------[ ) ]-----------------------> 6 (-1)
         *
         * @var int $state
         */
        $state = 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_OPERATOR && $token->value === '(') {
                    $state = 1;
                } else {
                    $parser->error(__('An opening bracket was expected.'), $token);
                    break;
                }
            } elseif ($state === 1) {
                if ($token->type === Token::TYPE_KEYWORD && $token->value === 'CONSTRAINT') {
                    $expr->isConstraint = true;
                } elseif ($token->type === Token::TYPE_KEYWORD && $token->flags & Token::FLAG_KEYWORD_KEY) {
                    $expr->key = Key::parse($parser, $list);
                    $state = 4;
                } elseif ($token->type === Token::TYPE_SYMBOL || $token->type === Token::TYPE_NONE) {
                    $expr->name = $token->value;
                    if (!$expr->isConstraint) {
                        $state = 2;
                    }
                } else {
                    if ($token->type === Token::TYPE_KEYWORD) {
                        if ($token->flags & Token::FLAG_KEYWORD_RESERVED) {
                            // Reserved keywords can't be used
                            // as field names without backquotes
                            $parser->error(__('A symbol name was expected! ' . 'A reserved keyword can not be used ' . 'as a column name without backquotes.'), $token);
                            return $ret;
                        } else {
                            // Non-reserved keywords are allowed without backquotes
                            $expr->name = $token->value;
                            $state = 2;
                        }
                    } else {
                        $parser->error(__('A symbol name was expected!'), $token);
                        return $ret;
                    }
                }
            } elseif ($state === 2) {
                $expr->type = DataType::parse($parser, $list);
                $state = 3;
            } elseif ($state === 3) {
                $expr->options = OptionsArray::parse($parser, $list, static::$FIELD_OPTIONS);
                $state = 4;
            } elseif ($state === 4) {
                if ($token->type === Token::TYPE_KEYWORD && $token->value === 'REFERENCES') {
                    ++$list->idx;
                    // Skipping keyword 'REFERENCES'.
                    $expr->references = Reference::parse($parser, $list);
                } else {
                    --$list->idx;
                }
                $state = 5;
            } elseif ($state === 5) {
                if (!empty($expr->type) || !empty($expr->key)) {
                    $ret[] = $expr;
                }
                $expr = new CreateDefinition();
                if ($token->value === ',') {
                    $state = 1;
                } elseif ($token->value === ')') {
                    $state = 6;
                    ++$list->idx;
                    break;
                } else {
                    $parser->error(__('A comma or a closing bracket was expected.'), $token);
                    $state = 0;
                    break;
                }
            }
        }
        // Last iteration was not saved.
        if (!empty($expr->type) || !empty($expr->key)) {
            $ret[] = $expr;
        }
        if ($state !== 0 && $state !== 6) {
            $parser->error(__('A closing bracket was expected.'), $list->tokens[$list->idx - 1]);
        }
        --$list->idx;
        return $ret;
    }

Usage Example

コード例 #1
0
 /**
  * @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 `CREATE`.
     // Parsing options.
     $this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
     ++$list->idx;
     // Skipping last option.
     // Parsing the field name.
     $this->name = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true, 'skipColumn' => true));
     if (empty($this->name)) {
         $parser->error(__('The name of the entity was expected.'), $list->tokens[$list->idx]);
     } else {
         ++$list->idx;
         // Skipping field.
     }
     if ($this->options->has('DATABASE')) {
         $this->entityOptions = OptionsArray::parse($parser, $list, static::$DB_OPTIONS);
     } elseif ($this->options->has('TABLE')) {
         $this->fields = CreateDefinition::parse($parser, $list);
         if (empty($this->fields)) {
             $parser->error(__('At least one column definition was expected.'), $list->tokens[$list->idx]);
         }
         ++$list->idx;
         $this->entityOptions = OptionsArray::parse($parser, $list, static::$TABLE_OPTIONS);
     } elseif ($this->options->has('PROCEDURE') || $this->options->has('FUNCTION')) {
         $this->parameters = ParameterDefinition::parse($parser, $list);
         if ($this->options->has('FUNCTION')) {
             $token = $list->getNextOfType(Token::TYPE_KEYWORD);
             if ($token->value !== 'RETURNS') {
                 $parser->error(__('A "RETURNS" keyword was expected.'), $token);
             } else {
                 ++$list->idx;
                 $this->return = DataType::parse($parser, $list);
             }
         }
         ++$list->idx;
         $this->entityOptions = OptionsArray::parse($parser, $list, static::$FUNC_OPTIONS);
         ++$list->idx;
         for (; $list->idx < $list->count; ++$list->idx) {
             $token = $list->tokens[$list->idx];
             $this->body[] = $token;
         }
     } else {
         if ($this->options->has('VIEW')) {
             $token = $list->getNext();
             // Skipping whitespaces and comments.
             // Parsing columns list.
             if ($token->type === Token::TYPE_OPERATOR && $token->value === '(') {
                 --$list->idx;
                 // getNext() also goes forward one field.
                 $this->fields = ArrayObj::parse($parser, $list);
                 ++$list->idx;
                 // Skipping last token from the array.
                 $list->getNext();
             }
             // Parsing the `AS` keyword.
             for (; $list->idx < $list->count; ++$list->idx) {
                 $token = $list->tokens[$list->idx];
                 if ($token->type === Token::TYPE_DELIMITER) {
                     break;
                 }
                 $this->body[] = $token;
             }
         } else {
             if ($this->options->has('TRIGGER')) {
                 // Parsing the time and the event.
                 $this->entityOptions = OptionsArray::parse($parser, $list, static::$TRIGGER_OPTIONS);
                 ++$list->idx;
                 $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'ON');
                 ++$list->idx;
                 // Skipping `ON`.
                 // Parsing the name of the table.
                 $this->table = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true, 'skipColumn' => true));
                 ++$list->idx;
                 $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'FOR EACH ROW');
                 ++$list->idx;
                 // Skipping `FOR EACH ROW`.
                 for (; $list->idx < $list->count; ++$list->idx) {
                     $token = $list->tokens[$list->idx];
                     $this->body[] = $token;
                 }
             }
         }
     }
 }
All Usage Examples Of SqlParser\Components\CreateDefinition::parse