Fix golint errors and export all returnable types

This commit is contained in:
Vladimir Hodakov 2019-10-19 01:17:00 +04:00
parent 3ab215ed63
commit ca047193ee
Signed by: Vladimir Hodakov
GPG Key ID: 673980B6882F82C6
10 changed files with 135 additions and 98 deletions

View File

@ -1,10 +1,10 @@
package jsonpath package jsonpath
const ( const (
BadStructure = "Bad Structure" BadStructure = "bad structure"
NoMoreResults = "No more results" NoMoreResults = "no more results"
UnexpectedToken = "Unexpected token in evaluation" UnexpectedToken = "unexpected token in evaluation"
AbruptTokenStreamEnd = "Token reader is not sending anymore tokens" AbruptTokenStreamEnd = "token reader is not sending anymore tokens"
) )
var ( var (

31
eval.go
View File

@ -49,7 +49,7 @@ func newEvaluation(tr tokenReader, paths ...*Path) *Eval {
location: *newStack(), location: *newStack(),
levelStack: *newIntStack(), levelStack: *newIntStack(),
state: evalRoot, state: evalRoot,
queries: make(map[string]*query, 0), queries: make(map[string]*query),
prevIndex: -1, prevIndex: -1,
nextKey: nil, nextKey: nil,
copyValues: true, // depends on which lexer is used copyValues: true, // depends on which lexer is used
@ -61,7 +61,7 @@ func newEvaluation(tr tokenReader, paths ...*Path) *Eval {
} }
// Determine whether to copy emitted item values ([]byte) from lexer // Determine whether to copy emitted item values ([]byte) from lexer
switch tr.(type) { switch tr.(type) {
case *readerLexer: case *ReaderLexer:
e.copyValues = true e.copyValues = true
default: default:
e.copyValues = false e.copyValues = false
@ -100,6 +100,7 @@ func (e *Eval) Iterate() (*Results, bool) {
for str, query := range e.queries { for str, query := range e.queries {
anyRunning = true anyRunning = true
query.state = query.state(query, e, t) query.state = query.state(query, e, t)
if query.state == nil { if query.state == nil {
delete(e.queries, str) delete(e.queries, str)
} }
@ -144,8 +145,8 @@ func (e *Eval) Next() (*Result, bool) {
} else { } else {
break break
} }
} }
return nil, false return nil, false
} }
@ -163,9 +164,12 @@ func (q *query) trySpillOver() {
if err != nil { if err != nil {
q.errors = append(q.errors, err) q.errors = append(q.errors, err)
} }
if exprRes { if exprRes {
next, ok := q.buckets.peek() next, ok := q.buckets.peek()
var spillover *Results var spillover *Results
if !ok { if !ok {
// fmt.Println("Spilling over into end queue") // fmt.Println("Spilling over into end queue")
spillover = q.resultQueue spillover = q.resultQueue
@ -174,6 +178,7 @@ func (q *query) trySpillOver() {
nextBucket := next.(exprBucket) nextBucket := next.(exprBucket)
spillover = nextBucket.results spillover = nextBucket.results
} }
for { for {
v := bucket.results.Pop() v := bucket.results.Pop()
if v != nil { if v != nil {
@ -191,7 +196,7 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
curLocation := e.location.len() - 1 curLocation := e.location.len() - 1
if q.loc() > curLocation { if q.loc() > curLocation {
q.pos -= 1 q.pos--
q.trySpillOver() q.trySpillOver()
} else if q.loc() <= curLocation { } else if q.loc() <= curLocation {
if q.loc() == curLocation-1 { if q.loc() == curLocation-1 {
@ -218,7 +223,6 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
q.buckets.push(bucket) q.buckets.push(bucket)
} }
} }
} }
} }
} }
@ -228,15 +232,17 @@ func pathMatchOp(q *query, e *Eval, i *Item) queryStateFn {
q.firstType = i.typ q.firstType = i.typ
q.buffer.Write(i.val) q.buffer.Write(i.val)
} }
q.valLoc = *e.location.clone() q.valLoc = *e.location.clone()
return pathEndValue return pathEndValue
} }
if q.loc() < -1 { if q.loc() < -1 {
return nil return nil
} else {
return pathMatchOp
} }
return pathMatchOp
} }
func pathEndValue(q *query, e *Eval, i *Item) queryStateFn { func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
@ -278,14 +284,16 @@ func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
q.valLoc = *newStack() q.valLoc = *newStack()
q.buffer.Truncate(0) q.buffer.Truncate(0)
q.pos -= 1 q.pos--
return pathMatchOp return pathMatchOp
} }
return pathEndValue return pathEndValue
} }
func (b *exprBucket) evaluate() (bool, error) { func (b *exprBucket) evaluate() (bool, error) {
values := make(map[string]Item) values := make(map[string]Item)
for _, q := range b.queries { for _, q := range b.queries {
result := q.resultQueue.Pop() result := q.resultQueue.Pop()
if result != nil { if result != nil {
@ -293,6 +301,7 @@ func (b *exprBucket) evaluate() (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
i := Item{ i := Item{
typ: t, typ: t,
val: result.Value, val: result.Value,
@ -305,11 +314,13 @@ func (b *exprBucket) evaluate() (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
res_bool, ok := res.(bool)
resBool, ok := res.(bool)
if !ok { if !ok {
return false, fmt.Errorf(exprErrorFinalValueNotBool, res) return false, fmt.Errorf(exprErrorFinalValueNotBool, res)
} }
return res_bool, nil
return resBool, nil
} }
func itemMatchOperator(loc interface{}, op *operator) bool { func itemMatchOperator(loc interface{}, op *operator) bool {

View File

@ -18,6 +18,7 @@ func evalRoot(e *Eval, i *Item) evalStateFn {
default: default:
e.Error = errors.New(UnexpectedToken) e.Error = errors.New(UnexpectedToken)
} }
return nil return nil
} }
@ -25,12 +26,16 @@ func evalObjectAfterOpen(e *Eval, i *Item) evalStateFn {
switch i.typ { switch i.typ {
case jsonKey: case jsonKey:
c := i.val[1 : len(i.val)-1] c := i.val[1 : len(i.val)-1]
if e.copyValues { if e.copyValues {
d := make([]byte, len(c)) d := make([]byte, len(c))
copy(d, c) copy(d, c)
c = d c = d
} }
e.nextKey = c e.nextKey = c
return evalObjectColon return evalObjectColon
case jsonBraceRight: case jsonBraceRight:
return rightBraceOrBracket(e) return rightBraceOrBracket(e)
@ -39,6 +44,7 @@ func evalObjectAfterOpen(e *Eval, i *Item) evalStateFn {
default: default:
e.Error = errors.New(UnexpectedToken) e.Error = errors.New(UnexpectedToken)
} }
return nil return nil
} }
@ -72,11 +78,13 @@ func evalObjectValue(e *Eval, i *Item) evalStateFn {
default: default:
e.Error = errors.New(UnexpectedToken) e.Error = errors.New(UnexpectedToken)
} }
return nil return nil
} }
func evalObjectAfterValue(e *Eval, i *Item) evalStateFn { func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
e.location.pop() e.location.pop()
switch i.typ { switch i.typ {
case jsonComma: case jsonComma:
return evalObjectAfterOpen return evalObjectAfterOpen
@ -87,6 +95,7 @@ func evalObjectAfterValue(e *Eval, i *Item) evalStateFn {
default: default:
e.Error = errors.New(UnexpectedToken) e.Error = errors.New(UnexpectedToken)
} }
return nil return nil
} }
@ -96,14 +105,15 @@ func rightBraceOrBracket(e *Eval) evalStateFn {
lowerTyp, ok := e.levelStack.peek() lowerTyp, ok := e.levelStack.peek()
if !ok { if !ok {
return evalRootEnd return evalRootEnd
} else { }
switch lowerTyp { switch lowerTyp {
case jsonBraceLeft: case jsonBraceLeft:
return evalObjectAfterValue return evalObjectAfterValue
case jsonBracketLeft: case jsonBracketLeft:
return evalArrayAfterValue return evalArrayAfterValue
} }
}
return nil return nil
} }

View File

@ -9,13 +9,13 @@ import (
) )
const ( const (
exprErrorMismatchedParens = "Mismatched parentheses" exprErrorMismatchedParens = "mismatched parentheses"
exprErrorBadExpression = "Bad Expression" exprErrorBadExpression = "bad expression"
exprErrorFinalValueNotBool = "Expression evaluated to a non-bool: %v" exprErrorFinalValueNotBool = "expression evaluated to a non-bool: %v"
exprErrorNotEnoughOperands = "Not enough operands for operation %q" exprErrorNotEnoughOperands = "not enough operands for operation %q"
exprErrorValueNotFound = "Value for %q not found" exprErrorValueNotFound = "value for %q not found"
exprErrorBadValue = "Bad value %q for type %q" exprErrorBadValue = "bad value %q for type %q"
exprErrorPathValueNotScalar = "Path value must be scalar value" exprErrorPathValueNotScalar = "path value must be scalar value"
) )
type exprErrorBadTypeComparison struct { type exprErrorBadTypeComparison struct {
@ -141,15 +141,16 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
if !ok { if !ok {
return false, fmt.Errorf(exprErrorValueNotFound, string(item.val)) return false, fmt.Errorf(exprErrorValueNotFound, string(item.val))
} }
switch i.typ { switch i.typ {
case jsonNull: case jsonNull:
s.push(nil) s.push(nil)
case jsonNumber: case jsonNumber:
val_float, err := strconv.ParseFloat(string(i.val), 64) valFloat, err := strconv.ParseFloat(string(i.val), 64)
if err != nil { if err != nil {
return false, fmt.Errorf(exprErrorBadValue, string(item.val), jsonTokenNames[jsonNumber]) return false, fmt.Errorf(exprErrorBadValue, string(item.val), jsonTokenNames[jsonNumber])
} }
s.push(val_float) s.push(valFloat)
case jsonKey, jsonString: case jsonKey, jsonString:
s.push(i.val) s.push(i.val)
default: default:
@ -173,14 +174,15 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
if !ok { if !ok {
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ]) return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
} }
switch p.(type) { switch p.(type) {
case nil: case nil:
err := take2Null(s, item.typ) err := take2Null(s, item.typ)
if err != nil { if err != nil {
return false, err return false, err
} else {
s.push(true)
} }
s.push(true)
case bool: case bool:
a, b, err := take2Bool(s, item.typ) a, b, err := take2Bool(s, item.typ)
if err != nil { if err != nil {
@ -205,14 +207,15 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
if !ok { if !ok {
return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ]) return false, fmt.Errorf(exprErrorNotEnoughOperands, exprTokenNames[item.typ])
} }
switch p.(type) { switch p.(type) {
case nil: case nil:
err := take2Null(s, item.typ) err := take2Null(s, item.typ)
if err != nil { if err != nil {
return true, err return true, err
} else {
s.push(false)
} }
s.push(false)
case bool: case bool:
a, b, err := take2Bool(s, item.typ) a, b, err := take2Bool(s, item.typ)
if err != nil { if err != nil {
@ -363,9 +366,9 @@ func take1Bool(s *stack, op int) (bool, error) {
} }
func take2Bool(s *stack, op int) (bool, bool, error) { func take2Bool(s *stack, op int) (bool, bool, error) {
a, a_err := take1Bool(s, op) a, aErr := take1Bool(s, op)
b, b_err := take1Bool(s, op) b, bErr := take1Bool(s, op)
return a, b, firstError(a_err, b_err) return a, b, firstError(aErr, bErr)
} }
func take1Float(s *stack, op int) (float64, error) { func take1Float(s *stack, op int) (float64, error) {
@ -383,9 +386,9 @@ func take1Float(s *stack, op int) (float64, error) {
} }
func take2Float(s *stack, op int) (float64, float64, error) { func take2Float(s *stack, op int) (float64, float64, error) {
a, a_err := take1Float(s, op) a, aErr := take1Float(s, op)
b, b_err := take1Float(s, op) b, bErr := take1Float(s, op)
return a, b, firstError(a_err, b_err) return a, b, firstError(aErr, bErr)
} }
func take1ByteSlice(s *stack, op int) ([]byte, error) { func take1ByteSlice(s *stack, op int) ([]byte, error) {
@ -403,9 +406,9 @@ func take1ByteSlice(s *stack, op int) ([]byte, error) {
} }
func take2ByteSlice(s *stack, op int) ([]byte, []byte, error) { func take2ByteSlice(s *stack, op int) ([]byte, []byte, error) {
a, a_err := take1ByteSlice(s, op) a, aErr := take1ByteSlice(s, op)
b, b_err := take1ByteSlice(s, op) b, bErr := take1ByteSlice(s, op)
return a, b, firstError(a_err, b_err) return a, b, firstError(aErr, bErr)
} }
func take1Null(s *stack, op int) error { func take1Null(s *stack, op int) error {
@ -422,7 +425,7 @@ func take1Null(s *stack, op int) error {
} }
func take2Null(s *stack, op int) error { func take2Null(s *stack, op int) error {
a_err := take1Null(s, op) aErr := take1Null(s, op)
b_err := take1Null(s, op) bErr := take1Null(s, op)
return firstError(a_err, b_err) return firstError(aErr, bErr)
} }

View File

@ -149,9 +149,9 @@ func TestExpressions(t *testing.T) {
items := readerToArray(lexer) items := readerToArray(lexer)
// trim EOF // trim EOF
items = items[0 : len(items)-1] items = items[0 : len(items)-1]
items_post, err := infixToPostFix(items) itemsPost, err := infixToPostFix(items)
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) { if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
val, err := evaluatePostFix(items_post, test.fields) val, err := evaluatePostFix(itemsPost, test.fields)
if as.NoError(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%q", test.input, test.fields, err) { if as.NoError(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%q", test.input, test.fields, err) {
as.EqualValues(test.expectedValue, val, "\nTest: %q\nActual: %v \nExpected %v\n", test.input, val, test.expectedValue) as.EqualValues(test.expectedValue, val, "\nTest: %q\nActual: %v \nExpected %v\n", test.input, val, test.expectedValue)
} }
@ -165,8 +165,8 @@ var exprErrorTests = []struct {
expectedErrorSubstring string expectedErrorSubstring string
}{ }{
{"@a == @b", map[string]Item{"@a": genValue(`"one"`, jsonString), "@b": genValue("3.4", jsonNumber)}, "cannot be compared"}, {"@a == @b", map[string]Item{"@a": genValue(`"one"`, jsonString), "@b": genValue("3.4", jsonNumber)}, "cannot be compared"},
{")(", nil, "Mismatched parentheses"}, {")(", nil, "mismatched parentheses"},
{")123", nil, "Mismatched parentheses"}, {")123", nil, "mismatched parentheses"},
{"20 == null", nil, "cannot be compared"}, {"20 == null", nil, "cannot be compared"},
{`"toronto" == null`, nil, "cannot be compared"}, {`"toronto" == null`, nil, "cannot be compared"},
{`false == 20`, nil, "cannot be compared"}, {`false == 20`, nil, "cannot be compared"},
@ -175,9 +175,9 @@ var exprErrorTests = []struct {
{`"toronto" != null`, nil, "cannot be compared"}, {`"toronto" != null`, nil, "cannot be compared"},
{`false != 20`, nil, "cannot be compared"}, {`false != 20`, nil, "cannot be compared"},
{`"nick" != 20`, nil, "cannot be compared"}, {`"nick" != 20`, nil, "cannot be compared"},
{``, nil, "Bad Expression"}, {``, nil, "bad expression"},
{`==`, nil, "Bad Expression"}, {`==`, nil, "bad expression"},
{`!=`, nil, "Not enough operands"}, {`!=`, nil, "not enough operands"},
{`!23`, nil, "cannot be compared"}, {`!23`, nil, "cannot be compared"},
{`"nick" || true`, nil, "cannot be compared"}, {`"nick" || true`, nil, "cannot be compared"},
@ -210,13 +210,13 @@ func TestBadExpressions(t *testing.T) {
items := readerToArray(lexer) items := readerToArray(lexer)
// trim EOF // trim EOF
items = items[0 : len(items)-1] items = items[0 : len(items)-1]
items_post, err := infixToPostFix(items) itemsPost, err := infixToPostFix(items)
if err != nil { if err != nil {
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %q does not contain %q", test.input, err.Error(), test.expectedErrorSubstring) as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %q does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
continue continue
} }
if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) { if as.NoError(err, "Could not transform to postfix\nTest: %q", test.input) {
_, err := evaluatePostFix(items_post, test.fields) _, err := evaluatePostFix(itemsPost, test.fields)
if as.Error(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%s", test.input, test.fields, err) { if as.Error(err, "Could not evaluate postfix\nTest Input: %q\nTest Values:%q\nError:%s", test.input, test.fields, err) {
as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %s does not contain %q", test.input, err.Error(), test.expectedErrorSubstring) as.True(strings.Contains(err.Error(), test.expectedErrorSubstring), "Test Input: %q\nError %s does not contain %q", test.input, err.Error(), test.expectedErrorSubstring)
} }

View File

@ -134,9 +134,9 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
case jsonBracketLeft: case jsonBracketLeft:
return stateJSONValue return stateJSONValue
case noValue: case noValue:
return l.errorf("Found %#U outside of array or object", cur) return l.errorf("found %#U outside of array or object", cur)
default: default:
return l.errorf("Unexpected character in lexer stack: %#U", cur) return l.errorf("unexpected character in lexer stack: %#U", cur)
} }
case '}': case '}':
l.emit(jsonBraceRight) l.emit(jsonBraceRight)
@ -145,7 +145,7 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
case jsonBraceLeft: case jsonBraceLeft:
return stateJSONAfterValue return stateJSONAfterValue
case jsonBracketLeft: case jsonBracketLeft:
return l.errorf("Unexpected %#U in array", cur) return l.errorf("unexpected %#U in array", cur)
case noValue: case noValue:
return stateJSONAfterRoot return stateJSONAfterRoot
} }
@ -154,7 +154,7 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
state.pop() state.pop()
switch topVal { switch topVal {
case jsonBraceLeft: case jsonBraceLeft:
return l.errorf("Unexpected %#U in object", cur) return l.errorf("unexpected %#U in object", cur)
case jsonBracketLeft: case jsonBracketLeft:
return stateJSONAfterValue return stateJSONAfterValue
case noValue: case noValue:
@ -164,11 +164,11 @@ func stateJSONAfterValue(l lexer, state *intStack) stateFn {
if state.len() == 0 { if state.len() == 0 {
l.emit(jsonEOF) l.emit(jsonEOF)
return nil return nil
} else {
return l.errorf("Unexpected EOF instead of value")
} }
return l.errorf("unexpected EOF instead of value")
default: default:
return l.errorf("Unexpected character after json value token: %#U", cur) return l.errorf("unexpected character after json value token: %#U", cur)
} }
return nil return nil
} }

View File

@ -8,7 +8,7 @@ import (
"io" "io"
) )
type readerLexer struct { type ReaderLexer struct {
lex lex
bufInput *bufio.Reader bufInput *bufio.Reader
input io.Reader input io.Reader
@ -17,8 +17,8 @@ type readerLexer struct {
lexeme *bytes.Buffer lexeme *bytes.Buffer
} }
func NewReaderLexer(rr io.Reader, initial stateFn) *readerLexer { func NewReaderLexer(rr io.Reader, initial stateFn) *ReaderLexer {
l := readerLexer{ l := ReaderLexer{
input: rr, input: rr,
bufInput: bufio.NewReader(rr), bufInput: bufio.NewReader(rr),
nextByte: noValue, nextByte: noValue,
@ -28,7 +28,7 @@ func NewReaderLexer(rr io.Reader, initial stateFn) *readerLexer {
return &l return &l
} }
func (l *readerLexer) take() int { func (l *ReaderLexer) take() int {
if l.nextByte == noValue { if l.nextByte == noValue {
l.peek() l.peek()
} }
@ -39,10 +39,10 @@ func (l *readerLexer) take() int {
return nr return nr
} }
func (l *readerLexer) takeString() error { func (l *ReaderLexer) takeString() error {
cur := l.take() cur := l.take()
if cur != '"' { if cur != '"' {
return fmt.Errorf("Expected \" as start of string instead of %#U", cur) return fmt.Errorf("expected \" as start of string instead of %#U", cur)
} }
var previous byte var previous byte
@ -50,7 +50,7 @@ looper:
for { for {
curByte, err := l.bufInput.ReadByte() curByte, err := l.bufInput.ReadByte()
if err == io.EOF { if err == io.EOF {
return errors.New("Unexpected EOF in string") return errors.New("unexpected EOF in string")
} }
l.lexeme.WriteByte(curByte) l.lexeme.WriteByte(curByte)
@ -60,7 +60,7 @@ looper:
} else { } else {
curByte, err = l.bufInput.ReadByte() curByte, err = l.bufInput.ReadByte()
if err == io.EOF { if err == io.EOF {
return errors.New("Unexpected EOF in string") return errors.New("unexpected EOF in string")
} }
l.lexeme.WriteByte(curByte) l.lexeme.WriteByte(curByte)
} }
@ -71,7 +71,7 @@ looper:
return nil return nil
} }
func (l *readerLexer) peek() int { func (l *ReaderLexer) peek() int {
if l.nextByte != noValue { if l.nextByte != noValue {
return l.nextByte return l.nextByte
} }
@ -86,7 +86,7 @@ func (l *readerLexer) peek() int {
return l.nextByte return l.nextByte
} }
func (l *readerLexer) emit(t int) { func (l *ReaderLexer) emit(t int) {
l.setItem(t, l.pos, l.lexeme.Bytes()) l.setItem(t, l.pos, l.lexeme.Bytes())
l.pos += Pos(l.lexeme.Len()) l.pos += Pos(l.lexeme.Len())
l.hasItem = true l.hasItem = true
@ -117,18 +117,18 @@ func (l *readerLexer) emit(t int) {
} }
} }
func (l *readerLexer) setItem(typ int, pos Pos, val []byte) { func (l *ReaderLexer) setItem(typ int, pos Pos, val []byte) {
l.item.typ = typ l.item.typ = typ
l.item.pos = pos l.item.pos = pos
l.item.val = val l.item.val = val
} }
func (l *readerLexer) ignore() { func (l *ReaderLexer) ignore() {
l.pos += Pos(l.lexeme.Len()) l.pos += Pos(l.lexeme.Len())
l.lexeme.Reset() l.lexeme.Reset()
} }
func (l *readerLexer) next() (*Item, bool) { func (l *ReaderLexer) next() (*Item, bool) {
l.lexeme.Reset() l.lexeme.Reset()
for { for {
if l.currentStateFn == nil { if l.currentStateFn == nil {
@ -145,14 +145,14 @@ func (l *readerLexer) next() (*Item, bool) {
return &l.item, false return &l.item, false
} }
func (l *readerLexer) errorf(format string, args ...interface{}) stateFn { func (l *ReaderLexer) errorf(format string, args ...interface{}) stateFn {
l.setItem(lexError, l.pos, []byte(fmt.Sprintf(format, args...))) l.setItem(lexError, l.pos, []byte(fmt.Sprintf(format, args...)))
l.lexeme.Truncate(0) l.lexeme.Truncate(0)
l.hasItem = true l.hasItem = true
return nil return nil
} }
func (l *readerLexer) reset() { func (l *ReaderLexer) reset() {
l.bufInput.Reset(l.input) l.bufInput.Reset(l.input)
l.lexeme.Reset() l.lexeme.Reset()
l.nextByte = noValue l.nextByte = noValue

View File

@ -5,31 +5,31 @@ import (
"fmt" "fmt"
) )
type sliceLexer struct { type SliceLexer struct {
lex lex
input []byte // the []byte being scanned. input []byte // the []byte being scanned.
start Pos // start position of this Item. start Pos // start position of this Item.
pos Pos // current position in the input pos Pos // current position in the input
} }
func NewSliceLexer(input []byte, initial stateFn) *sliceLexer { func NewSliceLexer(input []byte, initial stateFn) *SliceLexer {
l := &sliceLexer{ l := &SliceLexer{
lex: newLex(initial), lex: newLex(initial),
input: input, input: input,
} }
return l return l
} }
func (l *sliceLexer) take() int { func (l *SliceLexer) take() int {
if int(l.pos) >= len(l.input) { if int(l.pos) >= len(l.input) {
return eof return eof
} }
r := int(l.input[l.pos]) r := int(l.input[l.pos])
l.pos += 1 l.pos++
return r return r
} }
func (l *sliceLexer) takeString() error { func (l *SliceLexer) takeString() error {
curPos := l.pos curPos := l.pos
inputLen := len(l.input) inputLen := len(l.input)
@ -67,14 +67,14 @@ looper:
return nil return nil
} }
func (l *sliceLexer) peek() int { func (l *SliceLexer) peek() int {
if int(l.pos) >= len(l.input) { if int(l.pos) >= len(l.input) {
return eof return eof
} }
return int(l.input[l.pos]) return int(l.input[l.pos])
} }
func (l *sliceLexer) emit(t int) { func (l *SliceLexer) emit(t int) {
l.setItem(t, l.start, l.input[l.start:l.pos]) l.setItem(t, l.start, l.input[l.start:l.pos])
l.hasItem = true l.hasItem = true
@ -91,17 +91,17 @@ func (l *sliceLexer) emit(t int) {
l.start = l.pos l.start = l.pos
} }
func (l *sliceLexer) setItem(typ int, pos Pos, val []byte) { func (l *SliceLexer) setItem(typ int, pos Pos, val []byte) {
l.item.typ = typ l.item.typ = typ
l.item.pos = pos l.item.pos = pos
l.item.val = val l.item.val = val
} }
func (l *sliceLexer) ignore() { func (l *SliceLexer) ignore() {
l.start = l.pos l.start = l.pos
} }
func (l *sliceLexer) next() (*Item, bool) { func (l *SliceLexer) next() (*Item, bool) {
for { for {
if l.currentStateFn == nil { if l.currentStateFn == nil {
break break
@ -117,14 +117,14 @@ func (l *sliceLexer) next() (*Item, bool) {
return &l.item, false return &l.item, false
} }
func (l *sliceLexer) errorf(format string, args ...interface{}) stateFn { func (l *SliceLexer) errorf(format string, args ...interface{}) stateFn {
l.setItem(lexError, l.start, []byte(fmt.Sprintf(format, args...))) l.setItem(lexError, l.start, []byte(fmt.Sprintf(format, args...)))
l.start = l.pos l.start = l.pos
l.hasItem = true l.hasItem = true
return nil return nil
} }
func (l *sliceLexer) reset() { func (l *SliceLexer) reset() {
l.start = 0 l.start = 0
l.pos = 0 l.pos = 0
l.lex = newLex(l.initialState) l.lex = newLex(l.initialState)

27
path.go
View File

@ -33,6 +33,7 @@ type operator struct {
whereClause []Item whereClause []Item
} }
// nolint:gocognit
func genIndexKey(tr tokenReader) (*operator, error) { func genIndexKey(tr tokenReader) (*operator, error) {
k := &operator{} k := &operator{}
var t *Item var t *Item
@ -63,34 +64,36 @@ func genIndexKey(tr tokenReader) (*operator, error) {
if t, ok = tr.next(); !ok { if t, ok = tr.next(); !ok {
return nil, errors.New("Expected number or *, but got none") return nil, errors.New("Expected number or *, but got none")
} }
switch t.typ { switch t.typ {
case pathIndexRange: case pathIndexRange:
if t, ok = tr.next(); !ok { if t, ok = tr.next(); !ok {
return nil, errors.New("Expected number or *, but got none") return nil, errors.New("expected number or *, but got none")
} }
switch t.typ { switch t.typ {
case pathIndex: case pathIndex:
v, err := strconv.Atoi(string(t.val)) v, err := strconv.Atoi(string(t.val))
if err != nil { if err != nil {
return nil, fmt.Errorf("Could not parse %q into int64", t.val) return nil, fmt.Errorf("could not parse %q into int64", t.val)
} }
k.indexEnd = v - 1 k.indexEnd = v - 1
k.hasIndexEnd = true k.hasIndexEnd = true
if t, ok = tr.next(); !ok || t.typ != pathBracketRight { if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
return nil, errors.New("Expected ], but got none") return nil, errors.New("expected ], but got none")
} }
case pathBracketRight: case pathBracketRight:
k.hasIndexEnd = false k.hasIndexEnd = false
default: default:
return nil, fmt.Errorf("Unexpected value within brackets after index: %q", t.val) return nil, fmt.Errorf("unexpected value within brackets after index: %q", t.val)
} }
k.typ = opTypeIndexRange k.typ = opTypeIndexRange
case pathBracketRight: case pathBracketRight:
k.typ = opTypeIndex k.typ = opTypeIndex
default: default:
return nil, fmt.Errorf("Unexpected value within brackets after index: %q", t.val) return nil, fmt.Errorf("unexpected value within brackets after index: %q", t.val)
} }
case pathKey: case pathKey:
k.keyStrings = map[string]struct{}{ k.keyStrings = map[string]struct{}{
@ -99,10 +102,10 @@ func genIndexKey(tr tokenReader) (*operator, error) {
k.typ = opTypeName k.typ = opTypeName
if t, ok = tr.next(); !ok || t.typ != pathBracketRight { if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
return nil, errors.New("Expected ], but got none") return nil, errors.New("expected ], but got none")
} }
default: default:
return nil, fmt.Errorf("Unexpected value within brackets: %q", t.val) return nil, fmt.Errorf("unexpected value within brackets: %q", t.val)
} }
return k, nil return k, nil
@ -166,21 +169,26 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
return nil, errors.New("Unexpected root node after start") return nil, errors.New("Unexpected root node after start")
} }
continue continue
case pathCurrent: case pathCurrent:
if len(q.operators) != 0 { if len(q.operators) != 0 {
return nil, errors.New("Unexpected current node after start") return nil, errors.New("Unexpected current node after start")
} }
continue continue
case pathPeriod: case pathPeriod:
continue continue
case pathBracketLeft: case pathBracketLeft:
k, err := genIndexKey(tr) k, err := genIndexKey(tr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
q.operators = append(q.operators, k) q.operators = append(q.operators, k)
case pathKey: case pathKey:
keyName := p.val keyName := p.val
if len(p.val) == 0 { if len(p.val) == 0 {
return nil, fmt.Errorf("Key length is zero at %d", p.pos) return nil, fmt.Errorf("Key length is zero at %d", p.pos)
} }
@ -196,11 +204,15 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
}, },
}, },
) )
case pathWildcard: case pathWildcard:
q.operators = append(q.operators, &operator{typ: opTypeNameWild}) q.operators = append(q.operators, &operator{typ: opTypeNameWild})
case pathValue: case pathValue:
q.captureEndValue = true q.captureEndValue = true
case pathWhere: case pathWhere:
case pathExpression: case pathExpression:
if len(q.operators) == 0 { if len(q.operators) == 0 {
return nil, errors.New("Cannot add where clause on last key") return nil, errors.New("Cannot add where clause on last key")
@ -210,6 +222,7 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
return nil, errors.New("Expression on last key already set") return nil, errors.New("Expression on last key already set")
} }
last.whereClauseBytes = p.val last.whereClauseBytes = p.val
case pathError: case pathError:
return q, errors.New(string(p.val)) return q, errors.New(string(p.val))
} }

View File

@ -9,7 +9,7 @@ type Results struct {
func newResults() *Results { func newResults() *Results {
return &Results{ return &Results{
nodes: make([]*Result, 3, 3), nodes: make([]*Result, 3),
} }
} }