initial commit
This commit is contained in:
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Binaries for the current project
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Go build cache
|
||||
.cache/go-build/
|
||||
|
||||
# IDE-specific files and directories
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Operating system specific files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Test coverage output
|
||||
*.out
|
||||
|
||||
# Dependency management tools (if not vendoring)
|
||||
vendor/ # Uncomment if you are not vendoring dependencies
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
113
lexer/lexer.go
Normal file
113
lexer/lexer.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package lexer
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type regexPattern struct {
|
||||
regex *regexp.Regexp
|
||||
handler regexHandler
|
||||
}
|
||||
|
||||
type lexer struct {
|
||||
patterns []regexPattern
|
||||
Tokens []Token
|
||||
source string
|
||||
position int
|
||||
}
|
||||
|
||||
func createLexer(source string) *lexer {
|
||||
lex := &lexer{
|
||||
position: 0,
|
||||
source: source,
|
||||
Tokens: make([]Token, 0),
|
||||
patterns: []regexPattern{
|
||||
{regexp.MustCompile(`\s+`), defaultHandler(SPACE, " ")},
|
||||
{regexp.MustCompile(`\:`), defaultHandler(COLON, ":")},
|
||||
{regexp.MustCompile(`>=`), defaultHandler(MORE_EQUAL, ">=")},
|
||||
{regexp.MustCompile(`>`), defaultHandler(MORE, ">")},
|
||||
{regexp.MustCompile(`<=`), defaultHandler(LESS_EQUAL, "<=")},
|
||||
{regexp.MustCompile(`<`), defaultHandler(LESS, "<")},
|
||||
{regexp.MustCompile(`!=`), defaultHandler(NOT_EQUAL, "!=")},
|
||||
{regexp.MustCompile(`=`), defaultHandler(EQUAL, "=")},
|
||||
{regexp.MustCompile(`!`), defaultHandler(EXCLAMATION, "!")},
|
||||
{regexp.MustCompile(`\band\b|\bAND\b`), defaultHandler(AND, "and")},
|
||||
{regexp.MustCompile(`\bnot\b|\bNOT\b`), defaultHandler(NOT, "not")},
|
||||
{regexp.MustCompile(`\bor\b|\bOR\b`), defaultHandler(OR, "or")},
|
||||
{regexp.MustCompile(`\(`), defaultHandler(OPEN_BRACE, "(")},
|
||||
{regexp.MustCompile(`\)`), defaultHandler(CLOSED_BRACE, ")")},
|
||||
{regexp.MustCompile(`\|`), defaultHandler(PIPE, "|")},
|
||||
{regexp.MustCompile(`//(.*)$`), commentHandler}, //defaultHandler(COMMENT, value string)},
|
||||
{regexp.MustCompile(`[-+]?[0-9]`), numberHandler}, //NUMBER,
|
||||
{regexp.MustCompile(`([0-9]*\.?[0-9]+)`), floatHandler}, //FLOAT_NUMBER
|
||||
{regexp.MustCompile(`"([^"]*)"`), stringHandler}, //STRING_LITERAL,
|
||||
{regexp.MustCompile(`\b\w+\b`), symbolHandler}, //SYMBOL
|
||||
},
|
||||
}
|
||||
return lex
|
||||
}
|
||||
|
||||
func (this *lexer) incrementPosition(n int) {
|
||||
this.position += n
|
||||
}
|
||||
|
||||
func (this *lexer) push(token Token) {
|
||||
this.Tokens = append(this.Tokens, token)
|
||||
this.incrementPosition(len(token.value))
|
||||
}
|
||||
|
||||
func (lex *lexer) at() byte {
|
||||
return lex.source[lex.position]
|
||||
}
|
||||
|
||||
func (lex *lexer) currentString() string {
|
||||
return lex.source[lex.position:]
|
||||
}
|
||||
|
||||
func (lex *lexer) atEof() bool {
|
||||
return lex.position >= len(lex.source)
|
||||
}
|
||||
|
||||
type regexHandler func(lex *lexer, regex *regexp.Regexp)
|
||||
|
||||
func defaultHandler(tokenType TokenType, value string) regexHandler {
|
||||
return func(lex *lexer, regex *regexp.Regexp) {
|
||||
lex.push(Token{tokenType, value})
|
||||
}
|
||||
}
|
||||
|
||||
func stringHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
match := regex.FindStringIndex(lex.currentString())
|
||||
stringLiteral := lex.currentString()[match[0]:match[1]]
|
||||
|
||||
lex.push(Token{STRING_LITERAL, stringLiteral})
|
||||
}
|
||||
|
||||
func numberHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
match := regex.FindString(lex.currentString())
|
||||
lex.push(Token{NUMBER, match})
|
||||
}
|
||||
|
||||
func floatHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
match := regex.FindString(lex.currentString())
|
||||
lex.push(Token{NUMBER, match})
|
||||
}
|
||||
|
||||
func symbolHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
//todo: if reserved keyword, insert "IDENTIFIER" token
|
||||
match := regex.FindString(lex.currentString())
|
||||
lex.push(Token{SYMBOL, match})
|
||||
}
|
||||
|
||||
func skipHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
match := regex.FindStringIndex(lex.currentString())
|
||||
lex.incrementPosition(match[1])
|
||||
}
|
||||
|
||||
func commentHandler(lex *lexer, regex *regexp.Regexp) {
|
||||
match := regex.FindStringIndex(lex.currentString())
|
||||
if match != nil {
|
||||
lex.incrementPosition(match[1])
|
||||
}
|
||||
}
|
||||
49
lexer/tokens.go
Normal file
49
lexer/tokens.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package lexer
|
||||
|
||||
// что есть в запросе?
|
||||
// строковые литералы
|
||||
// двоеточия
|
||||
// знак равенства
|
||||
// знак неравенства
|
||||
// AND
|
||||
// NOT
|
||||
// открытые скобки
|
||||
// закрытые скобки
|
||||
// комментарии
|
||||
// пайп-символы
|
||||
// числа
|
||||
// строки
|
||||
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
SYMBOL TokenType = iota
|
||||
COLON
|
||||
EXCLAMATION
|
||||
EQUAL
|
||||
NOT_EQUAL
|
||||
AND
|
||||
NOT
|
||||
OR
|
||||
MORE
|
||||
LESS
|
||||
MORE_EQUAL
|
||||
LESS_EQUAL
|
||||
OPEN_BRACE
|
||||
CLOSED_BRACE
|
||||
COMMENT
|
||||
PIPE
|
||||
NUMBER
|
||||
FLOAT_NUMBER
|
||||
STRING_LITERAL
|
||||
SPACE
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
tokenType TokenType
|
||||
value string
|
||||
}
|
||||
|
||||
func Parse(str string) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user