mirror of
https://github.com/chaisql/chai.git
synced 2025-10-06 16:18:14 +08:00
390 lines
6.7 KiB
Go
390 lines
6.7 KiB
Go
package scanner
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
// Token is a lexical token of the Genji SQL language.
|
|
type Token int
|
|
|
|
// These are a comprehensive list of Genji SQL language tokens.
|
|
const (
|
|
// ILLEGAL Token, EOF, WS are Special Genji SQL tokens.
|
|
ILLEGAL Token = iota
|
|
EOF
|
|
WS
|
|
COMMENT
|
|
|
|
// IDENT and the following are Genji SQL literal tokens.
|
|
IDENT // main
|
|
NAMEDPARAM // $param
|
|
POSITIONALPARAM // ?
|
|
NUMBER // 12345.67
|
|
INTEGER // 12345
|
|
STRING // "abc"
|
|
BADSTRING // "abc
|
|
BADESCAPE // \q
|
|
TRUE // true
|
|
FALSE // false
|
|
NULL // NULL
|
|
REGEX // Regular expressions
|
|
BADREGEX // `.*
|
|
ELLIPSIS // ...
|
|
literalEnd
|
|
|
|
operatorBeg
|
|
// ADD and the following are Genji SQL Operators
|
|
ADD // +
|
|
SUB // -
|
|
MUL // *
|
|
DIV // /
|
|
MOD // %
|
|
BITWISEAND // &
|
|
BITWISEOR // |
|
|
BITWISEXOR // ^
|
|
|
|
AND // AND
|
|
OR // OR
|
|
|
|
EQ // =
|
|
NEQ // !=
|
|
EQREGEX // =~
|
|
NEQREGEX // !~
|
|
LT // <
|
|
LTE // <=
|
|
GT // >
|
|
GTE // >=
|
|
IN // IN
|
|
NIN // NOT IN
|
|
IS // IS
|
|
ISN // IS NOT
|
|
LIKE // LIKE
|
|
NLIKE // NOT LIKE
|
|
CONCAT // ||
|
|
BETWEEN // BETWEEN
|
|
operatorEnd
|
|
|
|
LPAREN // (
|
|
RPAREN // )
|
|
LBRACKET // {
|
|
RBRACKET // }
|
|
LSBRACKET // [
|
|
RSBRACKET // ]
|
|
COMMA // ,
|
|
COLON // :
|
|
DOUBLECOLON // ::
|
|
SEMICOLON // ;
|
|
DOT // .
|
|
|
|
keywordBeg
|
|
// ALL and the following are Genji SQL Keywords
|
|
ADD_KEYWORD
|
|
ALL
|
|
ALTER
|
|
AS
|
|
ASC
|
|
BEGIN
|
|
BY
|
|
CACHE
|
|
CAST
|
|
CHECK
|
|
COMMIT
|
|
CONFLICT
|
|
CONSTRAINT
|
|
CREATE
|
|
CYCLE
|
|
DEFAULT
|
|
DELETE
|
|
DESC
|
|
DISTINCT
|
|
DO
|
|
DROP
|
|
EXISTS
|
|
EXPLAIN
|
|
FIELD
|
|
FOR
|
|
FROM
|
|
GROUP
|
|
IF
|
|
IGNORE
|
|
INCREMENT
|
|
INDEX
|
|
INSERT
|
|
INTO
|
|
KEY
|
|
LIMIT
|
|
MAXVALUE
|
|
MINVALUE
|
|
NEXT
|
|
NO
|
|
NOT
|
|
NOTHING
|
|
OFFSET
|
|
ON
|
|
ONLY
|
|
ORDER
|
|
PRECISION
|
|
PRIMARY
|
|
READ
|
|
REINDEX
|
|
RENAME
|
|
REPLACE
|
|
RETURNING
|
|
ROLLBACK
|
|
SELECT
|
|
SEQUENCE
|
|
SET
|
|
START
|
|
TABLE
|
|
TO
|
|
TRANSACTION
|
|
UNION
|
|
UNIQUE
|
|
UNSET
|
|
UPDATE
|
|
VALUE
|
|
VALUES
|
|
WITH
|
|
WHERE
|
|
WRITE
|
|
|
|
// Types
|
|
TYPEANY
|
|
TYPEARRAY
|
|
TYPEBIGINT
|
|
TYPEBLOB
|
|
TYPEBOOL
|
|
TYPEBOOLEAN
|
|
TYPEBYTES
|
|
TYPECHARACTER
|
|
TYPEDOCUMENT
|
|
TYPEDOUBLE
|
|
TYPEINT
|
|
TYPEINT2
|
|
TYPEINT8
|
|
TYPEINTEGER
|
|
TYPEMEDIUMINT
|
|
TYPESMALLINT
|
|
TYPETEXT
|
|
TYPETINYINT
|
|
TYPEREAL
|
|
TYPEVARCHAR
|
|
|
|
keywordEnd
|
|
)
|
|
|
|
var tokens = [...]string{
|
|
ILLEGAL: "ILLEGAL",
|
|
EOF: "EOF",
|
|
WS: "WS",
|
|
|
|
IDENT: "IDENT",
|
|
POSITIONALPARAM: "?",
|
|
NUMBER: "NUMBER",
|
|
STRING: "STRING",
|
|
BADSTRING: "BADSTRING",
|
|
BADESCAPE: "BADESCAPE",
|
|
TRUE: "TRUE",
|
|
FALSE: "FALSE",
|
|
REGEX: "REGEX",
|
|
NULL: "NULL",
|
|
|
|
ADD: "+",
|
|
SUB: "-",
|
|
MUL: "*",
|
|
DIV: "/",
|
|
MOD: "%",
|
|
BITWISEAND: "&",
|
|
BITWISEOR: "|",
|
|
BITWISEXOR: "^",
|
|
BETWEEN: "BETWEEN",
|
|
|
|
AND: "AND",
|
|
OR: "OR",
|
|
|
|
EQ: "=",
|
|
NEQ: "!=",
|
|
EQREGEX: "=~",
|
|
NEQREGEX: "!~",
|
|
LT: "<",
|
|
LTE: "<=",
|
|
GT: ">",
|
|
GTE: ">=",
|
|
IN: "IN",
|
|
IS: "IS",
|
|
LIKE: "LIKE",
|
|
|
|
LPAREN: "(",
|
|
RPAREN: ")",
|
|
LBRACKET: "{",
|
|
RBRACKET: "}",
|
|
LSBRACKET: "[",
|
|
RSBRACKET: "]",
|
|
COMMA: ",",
|
|
COLON: ":",
|
|
DOUBLECOLON: "::",
|
|
SEMICOLON: ";",
|
|
DOT: ".",
|
|
|
|
ADD_KEYWORD: "ADD",
|
|
ALL: "ALL",
|
|
ALTER: "ALTER",
|
|
AS: "AS",
|
|
ASC: "ASC",
|
|
BEGIN: "BEGIN",
|
|
BY: "BY",
|
|
CACHE: "CACHE",
|
|
CAST: "CAST",
|
|
CHECK: "CHECK",
|
|
COMMIT: "COMMIT",
|
|
CONFLICT: "CONFLICT",
|
|
CONSTRAINT: "CONSTRAINT",
|
|
CREATE: "CREATE",
|
|
CYCLE: "CYCLE",
|
|
DO: "DO",
|
|
DEFAULT: "DEFAULT",
|
|
DELETE: "DELETE",
|
|
DESC: "DESC",
|
|
DISTINCT: "DISTINCT",
|
|
DROP: "DROP",
|
|
EXISTS: "EXISTS",
|
|
EXPLAIN: "EXPLAIN",
|
|
GROUP: "GROUP",
|
|
KEY: "KEY",
|
|
FIELD: "FIELD",
|
|
FOR: "FOR",
|
|
FROM: "FROM",
|
|
IF: "IF",
|
|
IGNORE: "IGNORE",
|
|
INCREMENT: "INCREMENT",
|
|
INDEX: "INDEX",
|
|
INSERT: "INSERT",
|
|
INTO: "INTO",
|
|
LIMIT: "LIMIT",
|
|
MAXVALUE: "MAXVALUE",
|
|
MINVALUE: "MINVALUE",
|
|
NEXT: "NEXT",
|
|
NO: "NO",
|
|
NOT: "NOT",
|
|
NOTHING: "NOTHING",
|
|
OFFSET: "OFFSET",
|
|
ON: "ON",
|
|
ONLY: "ONLY",
|
|
ORDER: "ORDER",
|
|
PRECISION: "PRECISION",
|
|
PRIMARY: "PRIMARY",
|
|
READ: "READ",
|
|
REINDEX: "REINDEX",
|
|
RENAME: "RENAME",
|
|
RETURNING: "RETURNING",
|
|
REPLACE: "REPLACE",
|
|
ROLLBACK: "ROLLBACK",
|
|
START: "START",
|
|
SELECT: "SELECT",
|
|
SET: "SET",
|
|
SEQUENCE: "SEQUENCE",
|
|
TABLE: "TABLE",
|
|
TO: "TO",
|
|
TRANSACTION: "TRANSACTION",
|
|
UNION: "UNION",
|
|
UNIQUE: "UNIQUE",
|
|
UNSET: "UNSET",
|
|
UPDATE: "UPDATE",
|
|
VALUE: "VALUE",
|
|
VALUES: "VALUES",
|
|
WITH: "WITH",
|
|
WHERE: "WHERE",
|
|
WRITE: "WRITE",
|
|
|
|
TYPEANY: "ANY",
|
|
TYPEARRAY: "ARRAY",
|
|
TYPEBIGINT: "BIGINT",
|
|
TYPEBLOB: "BLOB",
|
|
TYPEBOOL: "BOOL",
|
|
TYPEBOOLEAN: "BOOLEAN",
|
|
TYPEBYTES: "BYTES",
|
|
TYPECHARACTER: "CHARACTER",
|
|
TYPEDOCUMENT: "DOCUMENT",
|
|
TYPEDOUBLE: "DOUBLE",
|
|
TYPEINT: "INT",
|
|
TYPEINT2: "INT2",
|
|
TYPEINT8: "INT8",
|
|
TYPEINTEGER: "INTEGER",
|
|
TYPEMEDIUMINT: "MEDIUMINT",
|
|
TYPESMALLINT: "SMALLINT",
|
|
TYPETEXT: "TEXT",
|
|
TYPETINYINT: "TINYINT",
|
|
TYPEREAL: "REAL",
|
|
TYPEVARCHAR: "VARCHAR",
|
|
}
|
|
|
|
var keywords map[string]Token
|
|
|
|
// String returns the string representation of the token.
|
|
func (tok Token) String() string {
|
|
if tok >= 0 && tok < Token(len(tokens)) {
|
|
return tokens[tok]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Precedence returns the operator precedence of the binary operator token.
|
|
func (tok Token) Precedence() int {
|
|
switch tok {
|
|
case OR:
|
|
return 1
|
|
case AND:
|
|
return 2
|
|
case NOT:
|
|
return 3
|
|
case EQ, NEQ, IS, ISN, IN, NIN, LIKE, NLIKE, EQREGEX, NEQREGEX, BETWEEN:
|
|
return 4
|
|
case LT, LTE, GT, GTE:
|
|
return 5
|
|
case BITWISEOR, BITWISEXOR, BITWISEAND:
|
|
return 6
|
|
case ADD, SUB:
|
|
return 7
|
|
case MUL, DIV, MOD:
|
|
return 8
|
|
case CONCAT:
|
|
return 9
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// IsOperator returns true for operator tokens.
|
|
func (tok Token) IsOperator() bool { return tok > operatorBeg && tok < operatorEnd }
|
|
|
|
// Tokstr returns a literal if provided, otherwise returns the token string.
|
|
func Tokstr(tok Token, lit string) string {
|
|
if lit != "" {
|
|
return lit
|
|
}
|
|
return tok.String()
|
|
}
|
|
|
|
// lookup returns the token associated with a given string.
|
|
func lookup(ident string) Token {
|
|
if tok, ok := keywords[strings.ToLower(ident)]; ok {
|
|
return tok
|
|
}
|
|
return IDENT
|
|
}
|
|
|
|
// Pos specifies the line and character position of a token.
|
|
// The Char and Line are both zero-based indexes.
|
|
type Pos struct {
|
|
Line int
|
|
Char int
|
|
}
|
|
|
|
// AllKeywords returns all defined tokens corresponding to keywords.
|
|
func AllKeywords() []Token {
|
|
tokens := make([]Token, 0, len(keywords))
|
|
for _, tok := range keywords {
|
|
tokens = append(tokens, tok)
|
|
}
|
|
return tokens
|
|
}
|