nicer but my fsm is wrong if i want to bundle ands first
All checks were successful
cicd / ci (push) Successful in 3m29s

This commit is contained in:
Bel LaPointe
2024-12-13 10:49:19 -07:00
parent 012024ac66
commit d7edc1ff1d
2 changed files with 78 additions and 90 deletions

View File

@@ -2,7 +2,7 @@ package cli
import (
"fmt"
"io"
"log"
"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
)
@@ -10,67 +10,91 @@ import (
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
var result ledger.Like
var err error
func() {
defer func() {
if err := recover(); err != nil {
err = fmt.Errorf("panicked: %v", err)
}
}()
result, err = buildQuery(args)
}()
return result, err
}
func buildOneQuery(args args) (ledger.Like, error) {
word, ok := args.peek()
if !ok {
return nil, io.EOF
func buildQuery(args args) (ledger.Like, error) {
likeName := func(s string) ledger.Like {
return ledger.LikeName(s)
}
andLike := func(a, b ledger.Like) ledger.Like {
return (ledger.Likes{a, b}).All
}
orLike := func(a, b ledger.Like) ledger.Like {
return (ledger.Likes{a, b}).Any
}
notLike := func(a ledger.Like) ledger.Like {
return ledger.LikeNot(a)
}
likes := make(ledger.Likes, 0)
if !args.more() {
return likeName(""), nil
}
like := likeName("ajskfdlsjfkdasj")
for _, ok := args.peek(); ok; _, ok = args.peek() {
switch word {
for args.more() {
switch args.peek() {
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
var like ledger.Like
switch args.peek() {
case "not":
args.pop()
log.Println("and not", args.peek())
like = notLike(likeName(args.pop()))
default:
log.Println("and ", args.peek())
like = likeName(args.pop())
}
likes = append(likes, like)
like = andLike(like, like)
case "not":
args.pop()
like, err := buildOneQuery(args)
if err != nil {
return nil, err
}
likes = append(likes, like)
log.Println("or not ", args.peek())
like = orLike(like, notLike(
likeName(args.pop()),
))
default:
return nil, io.EOF
if next, _ := args.peek(); next != "and" {
return likes.All, nil
}
log.Println("or ", args.peek())
like = orLike(like,
likeName(args.pop()),
)
}
}
return nil, io.EOF
return like, nil
}
type args []string
func (args *args) pop() string {
first := (*args)[0]
*args = (*args)[1:]
if !args.more() {
panic("expected more arguments")
}
first := ""
if len(*args) > 0 {
first = (*args)[0]
*args = (*args)[1:]
}
return first
}
func (args *args) peek() (string, bool) {
func (args *args) peek() string {
if len(*args) == 0 {
return "", false
return ""
}
return (*args)[0], true
return (*args)[0]
}
func (args *args) more() bool {
return len(*args) > 0
}