mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
Add new lexer.
This commit is contained in:
parent
4e3203df16
commit
4fa9c329c2
3 changed files with 121 additions and 0 deletions
|
|
@ -9,6 +9,11 @@
|
|||
"version": "8a44ce0c654efd505418bb2c341cb9b797020583",
|
||||
"type": "git"
|
||||
},
|
||||
"goconvey": {
|
||||
"repo": "github.com/smartystreets/goconvey/convey",
|
||||
"version": "master",
|
||||
"type": "git"
|
||||
},
|
||||
"gocql": {
|
||||
"repo": "tux21b.org/v1/gocql",
|
||||
"version": "44eda643c1ae69e866e491b1c935c5b22e42350e",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,104 @@ package query
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"pilosa/db"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
const (
|
||||
TYPE_FUNC = iota
|
||||
TYPE_LP = iota
|
||||
TYPE_RP = iota
|
||||
TYPE_ID = iota
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
Text string
|
||||
Type int
|
||||
}
|
||||
|
||||
type statefn func(lexer *Lexer) statefn
|
||||
|
||||
type Lexer struct {
|
||||
text string
|
||||
pos int
|
||||
start int
|
||||
state int
|
||||
ch chan Token
|
||||
}
|
||||
|
||||
func (lexer *Lexer) emit(typ int) {
|
||||
lexer.ch <- Token{lexer.text[lexer.start:lexer.pos], typ}
|
||||
lexer.start = lexer.pos
|
||||
}
|
||||
|
||||
func (lexer *Lexer) accept(char uint8) error {
|
||||
for {
|
||||
if lexer.text[lexer.pos] == char {
|
||||
return nil
|
||||
}
|
||||
lexer.pos += 1
|
||||
if lexer.pos > len(lexer.text) {
|
||||
return errors.New("Parse error, expecting " + string(char))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stateFunc(lexer *Lexer) statefn {
|
||||
err := lexer.accept('(')
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
lexer.emit(TYPE_FUNC)
|
||||
return stateLP
|
||||
}
|
||||
|
||||
func stateLP(lexer *Lexer) statefn {
|
||||
lexer.pos += 1
|
||||
lexer.emit(TYPE_LP)
|
||||
return stateID
|
||||
}
|
||||
|
||||
func stateID(lexer *Lexer) statefn {
|
||||
err := lexer.accept(')')
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
lexer.emit(TYPE_ID)
|
||||
return stateRP
|
||||
}
|
||||
|
||||
func stateRP(lexer *Lexer) statefn {
|
||||
lexer.pos += 1
|
||||
lexer.emit(TYPE_RP)
|
||||
close(lexer.ch)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lexer *Lexer) Lex() []Token{
|
||||
tokens := make([]Token, 0)
|
||||
state := stateFunc
|
||||
go func () {
|
||||
for {
|
||||
state = state(lexer)
|
||||
if state == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
for t := range lexer.ch {
|
||||
spew.Dump(t)
|
||||
tokens = append(tokens, t)
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func Lex(input string) []Token {
|
||||
lexer := Lexer{input, 0, 0, TYPE_FUNC, make(chan Token)}
|
||||
return lexer.Lex()
|
||||
}
|
||||
|
||||
var InvalidQueryError = errors.New("Invalid query format.")
|
||||
|
||||
type QueryParser struct {
|
||||
|
|
|
|||
21
query/parser_test.go
Normal file
21
query/parser_test.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"testing"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
Convey("Basic parsing", t, func() {
|
||||
tokens := Lex("get(10)")
|
||||
So(len(tokens), ShouldEqual, 4)
|
||||
So(tokens[0].Text, ShouldEqual, "get")
|
||||
So(tokens[0].Type, ShouldEqual, TYPE_FUNC)
|
||||
So(tokens[1].Text, ShouldEqual, "(")
|
||||
So(tokens[1].Type, ShouldEqual, TYPE_LP)
|
||||
So(tokens[2].Text, ShouldEqual, "10")
|
||||
So(tokens[2].Type, ShouldEqual, TYPE_ID)
|
||||
So(tokens[3].Text, ShouldEqual, ")")
|
||||
So(tokens[3].Type, ShouldEqual, TYPE_RP)
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue