surrealpatch/sql/tokens.go

450 lines
7.4 KiB
Go
Raw Normal View History

2016-02-26 17:27:07 +00:00
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sql
2017-03-02 10:47:10 +00:00
import "strings"
2016-02-26 17:27:07 +00:00
// Token defines a lexical token
2016-11-04 10:01:19 +00:00
type Token int16
2016-02-26 17:27:07 +00:00
const (
// special
ILLEGAL Token = iota
EOF
WS
// literals
literalsBeg
2016-09-07 15:44:23 +00:00
DATE // 1970-01-01
TIME // 1970-01-01T00:00:00+00:00
JSON // {"test":true}
EXPR // something[0].value
2016-09-07 15:44:23 +00:00
IDENT // something
THING // @class:id
MODEL // [person|1..1000]
2016-09-07 15:44:23 +00:00
STRING // "something"
REGION // "a multiline \n string"
NUMBER // 123456
DOUBLE // 123.456
REGEX // /.*/
ARRAY // [0,1,2]
DURATION // 13h
PARAM // $1
2016-02-26 17:27:07 +00:00
OEDGE // ->
IEDGE // <-
BEDGE // <->
2016-02-26 17:27:07 +00:00
DOT // .
COMMA // ,
2016-09-06 13:30:59 +00:00
QMARK // ?
2016-02-26 17:27:07 +00:00
LPAREN // (
RPAREN // )
LBRACK // [
RBRACK // ]
COLON // :
SEMICOLON // ;
literalsEnd
// operators
operatorBeg
ADD // +
SUB // -
MUL // *
DIV // /
INC // +=
DEC // -=
EQ // =
2016-09-06 13:30:59 +00:00
EEQ // ==
EXC // !
2016-02-26 17:27:07 +00:00
NEQ // !=
2016-09-06 13:30:59 +00:00
NEE // !==
ANY // ?=
2016-02-26 17:27:07 +00:00
LT // <
LTE // <=
GT // >
GTE // >=
2016-09-06 13:30:59 +00:00
SIN // ∋
SNI // ∌
INS // ∈
NIS // ∉
MAT // ~
NAT // !~
MAY // ?~
2016-02-26 17:27:07 +00:00
operatorEnd
2017-11-16 20:53:13 +00:00
// keywords
2016-02-26 17:27:07 +00:00
keywordsBeg
2016-05-23 12:32:02 +00:00
AFTER
2016-09-06 13:30:59 +00:00
ALLCONTAINEDIN
2016-02-26 17:27:07 +00:00
AND
AS
ASC
2017-11-16 20:53:13 +00:00
ASSERT
2016-02-26 17:27:07 +00:00
AT
2016-05-23 12:32:02 +00:00
BEFORE
2016-09-06 13:30:59 +00:00
BEGIN
2016-05-23 12:32:02 +00:00
BOTH
2016-02-26 17:27:07 +00:00
BY
2016-09-06 13:30:59 +00:00
CANCEL
2017-11-16 20:53:13 +00:00
COLLATE
2016-02-26 17:27:07 +00:00
COLUMNS
2016-09-06 13:30:59 +00:00
COMMIT
2017-11-16 20:53:13 +00:00
CONNECT
2016-09-06 13:30:59 +00:00
CONTAINS
CONTAINSALL
CONTAINSNONE
CONTAINSSOME
2016-05-23 12:32:02 +00:00
CONTENT
2016-02-26 17:27:07 +00:00
CREATE
2016-05-23 12:32:02 +00:00
DATABASE
DB
2016-02-26 17:27:07 +00:00
DEFINE
DELETE
DESC
2016-05-23 12:32:02 +00:00
DIFF
2017-11-16 20:53:13 +00:00
DROP
ELSE
2016-02-26 17:27:07 +00:00
EMPTY
2017-11-16 20:53:13 +00:00
END
EVENT
2016-07-04 10:37:37 +00:00
EXPUNGE
2016-02-26 17:27:07 +00:00
FALSE
FETCH
2016-05-23 12:32:02 +00:00
FIELD
2016-09-06 13:30:59 +00:00
FOR
2016-02-26 17:27:07 +00:00
FROM
FULL
2016-02-26 17:27:07 +00:00
GROUP
2016-10-14 21:06:05 +00:00
IF
2016-02-26 17:27:07 +00:00
IN
INDEX
2016-09-19 10:08:44 +00:00
INFO
2017-11-16 20:53:13 +00:00
INSERT
INTO
2016-09-06 13:30:59 +00:00
IS
2017-11-16 20:53:13 +00:00
KILL
2016-09-06 13:30:59 +00:00
LET
2016-02-26 17:27:07 +00:00
LIMIT
2016-10-14 21:17:58 +00:00
LIVE
2016-11-13 19:21:34 +00:00
LOGIN
2016-05-23 12:32:02 +00:00
MERGE
2016-09-06 13:30:59 +00:00
MISSING
2016-05-23 12:32:02 +00:00
NAMESPACE
NONE
2016-09-06 13:30:59 +00:00
NONECONTAINEDIN
NOT
NS
2016-02-26 17:27:07 +00:00
NULL
2017-11-16 20:53:13 +00:00
NUMERIC
2016-02-26 17:27:07 +00:00
ON
OR
ORDER
2016-11-13 19:21:34 +00:00
PASSWORD
PERMISSIONS
PRIORITY
2017-11-16 20:53:13 +00:00
RAND
2016-02-26 17:27:07 +00:00
RELATE
REMOVE
2016-05-23 12:32:02 +00:00
RETURN
2018-04-14 16:55:05 +00:00
RUN
SCHEMAFULL
SCHEMALESS
SCOPE
2016-02-26 17:27:07 +00:00
SELECT
2016-10-18 13:27:17 +00:00
SESSION
2016-02-26 17:27:07 +00:00
SET
SIGNIN
SIGNUP
2016-09-06 13:30:59 +00:00
SOMECONTAINEDIN
2016-02-26 17:27:07 +00:00
START
2016-05-23 12:32:02 +00:00
TABLE
2017-11-16 20:53:13 +00:00
THEN
TIMEOUT
2016-02-26 17:27:07 +00:00
TO
2016-11-13 19:21:34 +00:00
TOKEN
2016-09-06 13:30:59 +00:00
TRANSACTION
2016-02-26 17:27:07 +00:00
TRUE
2016-05-23 12:32:02 +00:00
TYPE
2016-02-26 17:27:07 +00:00
UNIQUE
UPDATE
UPSERT
2016-05-23 12:32:02 +00:00
USE
2016-11-22 19:10:42 +00:00
VALUE
2016-02-26 17:27:07 +00:00
VERSION
2016-05-23 12:32:02 +00:00
VOID
2017-11-16 20:53:13 +00:00
WHEN
2016-02-26 17:27:07 +00:00
WHERE
WITH
2016-02-26 17:27:07 +00:00
keywordsEnd
)
var tokens = [...]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
WS: "WS",
// literals
2016-09-07 15:44:23 +00:00
DATE: "DATE",
TIME: "TIME",
JSON: "JSON",
EXPR: "EXPR",
2016-09-07 15:44:23 +00:00
IDENT: "IDENT",
THING: "THING",
MODEL: "MODEL",
2016-09-07 15:44:23 +00:00
STRING: "STRING",
REGION: "REGION",
NUMBER: "NUMBER",
DOUBLE: "DOUBLE",
REGEX: "REGEX",
ARRAY: "ARRAY",
DURATION: "DURATION",
PARAM: "PARAM",
2016-02-26 17:27:07 +00:00
OEDGE: "->",
IEDGE: "<-",
BEDGE: "<->",
2016-02-26 17:27:07 +00:00
DOT: ".",
COMMA: ",",
2016-09-06 13:30:59 +00:00
QMARK: "?",
2016-02-26 17:27:07 +00:00
LPAREN: "(",
RPAREN: ")",
LBRACK: "[",
RBRACK: "]",
COLON: ":",
SEMICOLON: ";",
// operators
ADD: "+",
SUB: "-",
MUL: "*",
DIV: "/",
INC: "+=",
DEC: "-=",
EQ: "=",
2016-09-06 13:30:59 +00:00
EEQ: "==",
EXC: "!",
2016-02-26 17:27:07 +00:00
NEQ: "!=",
2016-09-06 13:30:59 +00:00
NEE: "!==",
ANY: "?=",
2016-02-26 17:27:07 +00:00
LT: "<",
LTE: "<=",
GT: ">",
GTE: ">=",
2016-09-06 13:30:59 +00:00
SIN: "∋",
SNI: "∌",
INS: "∈",
NIS: "∉",
MAT: "~",
NAT: "!~",
MAY: "?~",
2016-09-06 13:30:59 +00:00
2016-02-26 17:27:07 +00:00
// keywords
2016-09-06 13:30:59 +00:00
AFTER: "AFTER",
ALLCONTAINEDIN: "ALLCONTAINEDIN",
AND: "AND",
AS: "AS",
ASC: "ASC",
2017-11-16 20:53:13 +00:00
ASSERT: "ASSERT",
2016-09-06 13:30:59 +00:00
AT: "AT",
BEFORE: "BEFORE",
BEGIN: "BEGIN",
BOTH: "BOTH",
BY: "BY",
CANCEL: "CANCEL",
2017-11-16 20:53:13 +00:00
COLLATE: "COLLATE",
2016-09-06 13:30:59 +00:00
COLUMNS: "COLUMNS",
COMMIT: "COMMIT",
2017-11-16 20:53:13 +00:00
CONNECT: "CONNECT",
2016-09-06 13:30:59 +00:00
CONTAINS: "CONTAINS",
CONTAINSALL: "CONTAINSALL",
CONTAINSNONE: "CONTAINSNONE",
CONTAINSSOME: "CONTAINSSOME",
CONTENT: "CONTENT",
CREATE: "CREATE",
DATABASE: "DATABASE",
DB: "DB",
2016-09-06 13:30:59 +00:00
DEFINE: "DEFINE",
DELETE: "DELETE",
DESC: "DESC",
DIFF: "DIFF",
2017-11-16 20:53:13 +00:00
DROP: "DROP",
ELSE: "ELSE",
2016-09-06 13:30:59 +00:00
EMPTY: "EMPTY",
2017-11-16 20:53:13 +00:00
END: "END",
EVENT: "EVENT",
2016-09-06 13:30:59 +00:00
EXPUNGE: "EXPUNGE",
FALSE: "FALSE",
FETCH: "FETCH",
2016-09-06 13:30:59 +00:00
FIELD: "FIELD",
FOR: "FOR",
FROM: "FROM",
FULL: "FULL",
2016-09-06 13:30:59 +00:00
GROUP: "GROUP",
2016-10-14 21:06:05 +00:00
IF: "IF",
2016-09-06 13:30:59 +00:00
IN: "IN",
INDEX: "INDEX",
2016-09-19 10:08:44 +00:00
INFO: "INFO",
2017-11-16 20:53:13 +00:00
INSERT: "INSERT",
INTO: "INTO",
2016-09-06 13:30:59 +00:00
IS: "IS",
2017-11-16 20:53:13 +00:00
KILL: "KILL",
2016-09-06 13:30:59 +00:00
LET: "LET",
LIMIT: "LIMIT",
2016-10-14 21:17:58 +00:00
LIVE: "LIVE",
2016-11-13 19:21:34 +00:00
LOGIN: "LOGIN",
2016-09-06 13:30:59 +00:00
MERGE: "MERGE",
MISSING: "MISSING",
NAMESPACE: "NAMESPACE",
NONE: "NONE",
NONECONTAINEDIN: "NONECONTAINEDIN",
NOT: "NOT",
NS: "NS",
2016-09-06 13:30:59 +00:00
NULL: "NULL",
2017-11-16 20:53:13 +00:00
NUMERIC: "NUMERIC",
2016-09-06 13:30:59 +00:00
ON: "ON",
OR: "OR",
ORDER: "ORDER",
2016-11-13 19:21:34 +00:00
PASSWORD: "PASSWORD",
PERMISSIONS: "PERMISSIONS",
PRIORITY: "PRIORITY",
2017-11-16 20:53:13 +00:00
RAND: "RAND",
2016-09-06 13:30:59 +00:00
RELATE: "RELATE",
REMOVE: "REMOVE",
RETURN: "RETURN",
2018-04-14 16:55:05 +00:00
RUN: "RUN",
SCHEMAFULL: "SCHEMAFULL",
SCHEMALESS: "SCHEMALESS",
SCOPE: "SCOPE",
2016-09-06 13:30:59 +00:00
SELECT: "SELECT",
2016-10-18 13:27:17 +00:00
SESSION: "SESSION",
2016-09-06 13:30:59 +00:00
SET: "SET",
SIGNIN: "SIGNIN",
SIGNUP: "SIGNUP",
2016-09-06 13:30:59 +00:00
SOMECONTAINEDIN: "SOMECONTAINEDIN",
START: "START",
TABLE: "TABLE",
2017-11-16 20:53:13 +00:00
THEN: "THEN",
TIMEOUT: "TIMEOUT",
2016-09-06 13:30:59 +00:00
TO: "TO",
2016-11-13 19:21:34 +00:00
TOKEN: "TOKEN",
2016-09-06 13:30:59 +00:00
TRANSACTION: "TRANSACTION",
TRUE: "TRUE",
TYPE: "TYPE",
UNIQUE: "UNIQUE",
UPDATE: "UPDATE",
UPSERT: "UPSERT",
USE: "USE",
2016-11-22 19:10:42 +00:00
VALUE: "VALUE",
2016-09-06 13:30:59 +00:00
VERSION: "VERSION",
VOID: "VOID",
2017-11-16 20:53:13 +00:00
WHEN: "WHEN",
2016-09-06 13:30:59 +00:00
WHERE: "WHERE",
WITH: "WITH",
2016-02-26 17:27:07 +00:00
}
var literals map[string]Token
var operator map[string]Token
var keywords map[string]Token
func init() {
literals = make(map[string]Token)
for tok := literalsBeg + 1; tok < literalsEnd; tok++ {
literals[tokens[tok]] = tok
}
operator = make(map[string]Token)
for tok := operatorBeg + 1; tok < operatorEnd; tok++ {
operator[tokens[tok]] = tok
}
keywords = make(map[string]Token)
for tok := keywordsBeg + 1; tok < keywordsEnd; tok++ {
keywords[tokens[tok]] = tok
}
}
func lookup(lookups []Token) (literals []string) {
for _, token := range lookups {
literals = append(literals, token.String())
}
return
}
func (tok Token) precedence() int {
switch tok {
case OR, AND:
2016-02-26 17:27:07 +00:00
return 1
2016-09-06 13:30:59 +00:00
case EQ, NEQ, EEQ, NEE,
LT, LTE, GT, GTE,
ANY, SIN, SNI, INS, NIS, MAT, NAT, MAY,
2016-09-06 13:30:59 +00:00
CONTAINSALL, CONTAINSNONE, CONTAINSSOME,
ALLCONTAINEDIN, NONECONTAINEDIN, SOMECONTAINEDIN:
return 2
2016-02-26 17:27:07 +00:00
case ADD, SUB:
return 3
2016-02-26 17:27:07 +00:00
case MUL, DIV:
return 4
2016-02-26 17:27:07 +00:00
}
return 0
}
func (tok Token) String() string {
if tok >= 0 && tok < Token(len(tokens)) {
return tokens[tok]
}
return ""
}
2017-11-16 20:53:13 +00:00
func newToken(s string) Token {
for k, v := range tokens {
2017-11-16 20:53:13 +00:00
if len(v) == len(s) {
if strings.EqualFold(v, s) {
return Token(k)
}
}
}
return ILLEGAL
}
2016-02-26 17:27:07 +00:00
func (tok Token) isLiteral() bool { return tok > literalsBeg && tok < literalsEnd }
func (tok Token) isKeyword() bool { return tok > keywordsBeg && tok < keywordsEnd }
func (tok Token) isOperator() bool { return tok > operatorBeg && tok < operatorEnd }