ana-ledger/cmd/cli/query.go

77 lines
1.3 KiB
Go

package cli
import (
"fmt"
"io"
"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
)
type Query struct{}
func BuildQuery(args args) (ledger.Like, error) {
likes := make(ledger.Likes, 0)
for _, ok := args.peek(); ok; _, ok = args.peek() {
like, err := buildOneQuery(args)
if err != nil {
return nil, err
}
likes = append(likes, like)
}
return likes.Any, nil
}
func buildOneQuery(args args) (ledger.Like, error) {
word, ok := args.peek()
if !ok {
return nil, io.EOF
}
likes := make(ledger.Likes, 0)
for _, ok := args.peek(); ok; _, ok = args.peek() {
switch word {
case "and":
if len(likes) == 0 {
return nil, fmt.Errorf("and without predicate")
}
args.pop()
like, err := buildOneQuery(args)
if err != nil {
return nil, err
}
likes = append(likes, like)
case "not":
args.pop()
like, err := buildOneQuery(args)
if err != nil {
return nil, err
}
likes = append(likes, like)
default:
return nil, io.EOF
if next, _ := args.peek(); next != "and" {
return likes.All, nil
}
}
}
return nil, io.EOF
}
type args []string
func (args *args) pop() string {
first := (*args)[0]
*args = (*args)[1:]
return first
}
func (args *args) peek() (string, bool) {
if len(*args) == 0 {
return "", false
}
return (*args)[0], true
}