// LexDdlTable data definition language table
489267
func LexDdlTable(l *Lexer) StateFn {

	/*
		CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
		    (create_definition,...)
		    [table_options]
		    [partition_options]

		CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
		    [(create_definition,...)]
		    [table_options]
		    [partition_options]
		    [IGNORE | REPLACE]
		    [AS] query_expression

		CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
		    { LIKE old_tbl_name | (LIKE old_tbl_name) }

		CREATE TABLE `City` (
		  `ID` int(11) NOT NULL AUTO_INCREMENT,
		  `Name` char(35) NOT NULL DEFAULT '',
		  `CountryCode` char(3) NOT NULL DEFAULT '',
		  `District` char(20) NOT NULL DEFAULT '',
		  `Population` int(11) NOT NULL DEFAULT '0',
		  PRIMARY KEY (`ID`),
		  KEY `CountryCode` (`CountryCode`),
		  CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`)
		     REFERENCES `Country` (`Code`)
		) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8
	*/
	l.SkipWhiteSpaces()
	r := l.Next()

	//u.Debugf("LexDdlTable  r= '%v'", string(r))

	// Cover the logic and grouping
	switch r {
	case '(':
		// Start of columns
		l.Emit(TokenLeftParenthesis)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		return LexIdentifier
	case ')':
		// end of columns
		l.Emit(TokenRightParenthesis)
		return LexDdlTableStorage
	case '-', '/': // comment?
		p := l.Peek()
		if p == '-' {
			l.backup()
			l.Push("LexDdlTable", LexDdlTable)
			return LexInlineComment
		}
		u.Warnf("unhandled comment non inline ")
	case ';':
		l.backup()
		return nil
	}

	l.backup()
	word := strings.ToLower(l.PeekWord())
	//u.Debugf("looking table col start:  word=%s", word)
	r = l.Peek()
	if r == ',' {
		l.Emit(TokenComma)
		l.Push("LexDdlTable", l.clauseState())
		return LexExpressionOrIdentity
	}
	if l.isNextKeyword(word) {
		return nil
	}
	// ensure we don't get into a recursive death spiral here?
	if len(l.stack) < 10 {
		l.Push("LexDdlTable", LexDdlTable)
	} else {
		u.Errorf("Gracefully refusing to add more LexDdlTable: ")
	}
	return LexExpressionOrIdentity
}
539384
func lexIncludeString(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case isNL(r) || r == eof || r == optValTerm || r == mapEnd || isWhitespace(r):
		lx.backup()
		lx.emit(itemInclude)
		return lx.pop()
	case r == sqStringEnd:
		lx.backup()
		lx.emit(itemInclude)
		lx.next()
		lx.ignore()
		return lx.pop()
	}
	return lexIncludeString
}
21757
func NewTable() *Table {
	return &Table{
		Box:          NewBox(),
		bordersColor: Styles.GraphicsColor,
		separator:    ' ',
		lastColumn:   -1,
	}
}
1286504
func lexFloat(lx *lexer) stateFn {
	r := lx.next()
	if isDigit(r) {
		return lexFloat
	}

	lx.backup()
	lx.emit(itemFloat)
	return lx.pop()
}
976962
func lexAfterDataPrefix(l *lexer) stateFn {
	switch r := l.next(); {
	case r == paramSemicolon:
		l.backup()
		return lexParamSemicolon
	case r == dataComma:
		l.backup()
		return lexDataComma
	case r == eof:
		return l.errorf("missing comma before data")
	case r == 'x' || r == 'X':
		if l.next() == '-' {
			return lexXTokenMediaType
		}
		return lexInDiscreteMediaType
	case isTokenRune(r):
		return lexInDiscreteMediaType
	default:
		return l.errorf("invalid character after data prefix")
	}
}
1326917
func lexPredicateOrLiteral(l *lexer) stateFn {
	text := l.input[l.pos:]
	// Fix issue 39 (https://github.com/google/badwolf/issues/39)
	pIdx, lIdx := strings.Index(text, "\"@["), strings.Index(text, "\"^^type:")
	if pIdx < 0 && lIdx < 0 {
		l.emitError("failed to parse predicate or literal for opening \" delimiter")
		return nil
	}
	if pIdx > 0 && (lIdx < 0 || pIdx < lIdx) {
		return lexPredicate
	}
	return lexLiteral
}
700273
func lexBinding(l *lexer) stateFn {
	for {
		if r := l.next(); !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != rune('_') || r == eof {
			l.backup()
			l.emit(ItemBinding)
			break
		}
	}
	return lexSpace
}
375847
func (l *tomlLexer) lexVoid() tomlLexStateFn {
	for {
		next := l.peek()
		switch next {
		case '[':
			return l.lexTableKey
		case '#':
			return l.lexComment(l.lexVoid)
		case '=':
			return l.lexEqual
		case '\r':
			fallthrough
		case '\n':
			l.skip()
			continue
		}

		if isSpace(next) {
			l.skip()
		}

		if l.depth > 0 {
			return l.lexRvalue
		}

		if isKeyStartChar(next) {
			return l.lexKey
		}

		if next == eof {
			l.next()
			break
		}
	}

	l.emit(tokenEOF)
	return nil
}
329085
func lexInlineTableEnd(lx *lexer) stateFn {
	lx.ignore()
	lx.emit(itemInlineTableEnd)
	return lx.pop()
}
87514
func lexMapEnd(lx *lexer) stateFn {
	lx.ignore()
	lx.emit(itemMapEnd)
	return lx.pop()
}
781413
func Lexer(def lexer.Definition) Option {
	return func(p *Parser) error {
		p.lex = def
		return nil
	}
}
881432
func lexIncludeStart(lx *lexer) stateFn {
	r := lx.next()
	if isWhitespace(r) {
		return lexSkip(lx, lexIncludeStart)
	}
	lx.backup()
	return lexInclude
}
292862
func lexIncludeQuotedString(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case r == sqStringEnd:
		lx.backup()
		lx.emit(itemInclude)
		lx.next()
		lx.ignore()
		return lx.pop()
	}
	return lexIncludeQuotedString
}
534778
func ParseStrictDDL(sql string) (Statement, error) {
	tokenizer := NewStringTokenizer(sql)
	if yyParsePooled(tokenizer) != 0 {
		return nil, tokenizer.LastError
	}
	if tokenizer.ParseTree == nil {
		return nil, ErrEmpty
	}
	return tokenizer.ParseTree, nil
}
1355256
func (tkn *Tokenizer) Lex(lval *yySymType) int {
	if tkn.SkipToEnd {
		return tkn.skipStatement()
	}

	typ, val := tkn.Scan()
	for typ == COMMENT {
		if tkn.AllowComments {
			break
		}
		typ, val = tkn.Scan()
	}
	if typ == 0 || typ == ';' || typ == LEX_ERROR {
		// If encounter end of statement or invalid token,
		// we should not accept partially parsed DDLs. They
		// should instead result in parser errors. See the
		// Parse function to see how this is handled.
		tkn.partialDDL = nil
	}
	lval.bytes = val
	tkn.lastToken = val
	return typ
}
762865
func (s *Scratch) allocDtable() {
	tableSize := 1 << s.actualTableLog
	if cap(s.decTable) < int(tableSize) {
		s.decTable = make([]decSymbol, tableSize)
	}
	s.decTable = s.decTable[:tableSize]

	if cap(s.ct.tableSymbol) < 256 {
		s.ct.tableSymbol = make([]byte, 256)
	}
	s.ct.tableSymbol = s.ct.tableSymbol[:256]

	if cap(s.ct.stateTable) < 256 {
		s.ct.stateTable = make([]uint16, 256)
	}
	s.ct.stateTable = s.ct.stateTable[:256]
}
856900
func LexDdlTableColumn(l *Lexer) StateFn {

	/*
		http://dev.mysql.com/doc/refman/5.7/en/create-table.html

		create_definition:
		    col_name column_definition
		  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
		      [index_option] ...
		  | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
		      [index_option] ...
		  | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
		      [index_name] [index_type] (index_col_name,...)
		      [index_option] ...
		  | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)
		      [index_option] ...
		  | [CONSTRAINT [symbol]] FOREIGN KEY
		      [index_name] (index_col_name,...) reference_definition
		  | CHECK (expr)

		column_definition:
		    data_type [NOT NULL | NULL] [DEFAULT default_value]
		      [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
		      [COMMENT 'string']
		      [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]
		      [STORAGE {DISK|MEMORY|DEFAULT}]
		      [reference_definition]
		  | data_type [GENERATED ALWAYS] AS (expression)
		      [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
		      [NOT NULL | NULL] [[PRIMARY] KEY]
	*/
	l.SkipWhiteSpaces()
	r := l.Next()

	//u.Debugf("LexDdlTableColumn  r= '%v'  peek: %s", string(r), l.PeekX(20))

	//
	switch r {
	case '-', '/': // comment?
		p := l.Peek()
		if p == '-' {
			l.backup()
			l.Push("LexDdlTableColumn", LexDdlTableColumn)
			return LexInlineComment
		}
	case ';':
		l.backup()
		return nil
	case '(':
		l.Emit(TokenLeftParenthesis)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		l.Push("LexParenRight", LexParenRight)
		return LexListOfArgs
	case ')':
		l.Emit(TokenRightParenthesis)
		return nil
	case ',':
		l.Emit(TokenComma)
		return LexDdlTableColumn
	}

	l.backup()
	word := strings.ToLower(l.PeekWord())
	//u.Debugf("looking for ddl col start:  word=%s", word)
	switch word {
	case "primary":
		l.ConsumeWord(word)
		l.Emit(TokenPrimary)
		return LexDdlTableColumn
	case "not":
		l.ConsumeWord(word)
		l.Emit(TokenNegate)
		return LexDdlTableColumn
	case "null":
		l.ConsumeWord(word)
		l.Emit(TokenNull)
		return LexDdlTableColumn
	case "default":
		l.ConsumeWord(word)
		l.Emit(TokenDefault)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		return LexValue
	case "auto_increment":
		l.ConsumeWord(word)
		l.Emit(TokenIdentity)
		return LexDdlTableColumn
	case "unique":
		l.ConsumeWord(word)
		l.Emit(TokenUnique)
		return LexDdlTableColumn
	case "foreign":
		l.ConsumeWord(word)
		l.Emit(TokenForeign)
		return LexDdlTableColumn
	case "key":
		l.ConsumeWord(word)
		l.Emit(TokenKey)
		return LexDdlTableColumn
	case "constraint":
		l.ConsumeWord(word)
		l.Emit(TokenConstraint)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		return LexIdentifier
	case "references":
		l.ConsumeWord(word)
		l.Emit(TokenReferences)
		return LexDdlTableColumn
	case "comment":
		l.ConsumeWord(word)
		l.Emit(TokenIdentity)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		return LexValue
	// Character set is end of ddl column
	// case "character": // character set
	// 	cs := strings.ToLower(l.PeekX(len("character set")))
	// 	if cs == "character set" {
	// 		l.ConsumeWord(cs)
	// 		l.Emit(TokenCharacterSet)
	// 		l.Push("LexDdlTableColumn", LexDdlTableColumn)
	// 		return nil
	// 	}
	// Below here are Data Types
	case "int", "integer":
		l.ConsumeWord(word)
		l.Emit(TokenTypeInteger)
		p := l.Peek()
		if p == '(' {
			l.Push("LexDdlTableColumn", LexDdlTableColumn)
			l.Push("LexParenRight", LexParenRight)
			return LexListOfArgs
		}
		return LexDdlTableColumn
	case "text":
		l.ConsumeWord(word)
		l.Emit(TokenTypeText)
		return LexDdlTableColumn
	case "bigint":
		l.ConsumeWord(word)
		l.Emit(TokenTypeBigInt)
		p := l.Peek()
		if p == '(' {
			l.Push("LexDdlTableColumn", LexDdlTableColumn)
			l.Push("LexParenRight", LexParenRight)
			return LexListOfArgs
		}
		return LexDdlTableColumn
	case "varchar":
		l.ConsumeWord(word)
		l.Emit(TokenTypeVarChar)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		l.Push("LexParenRight", LexParenRight)
		return LexListOfArgs
	case "char":
		l.ConsumeWord(word)
		l.Emit(TokenTypeChar)
		l.Push("LexDdlTableColumn", LexDdlTableColumn)
		l.Push("LexParenRight", LexParenRight)
		return LexListOfArgs
	default:
		if l.isIdentity() {
			l.ConsumeWord(word)
			l.Emit(TokenIdentity)
			return LexDdlTableColumn
		}
	}

	u.Warnf("Did not find anything %s", word)
	return nil
}