diff --git a/rules.go b/rules.go new file mode 100644 index 0000000..b937e5b --- /dev/null +++ b/rules.go @@ -0,0 +1,44 @@ +package main + +import "strings" + +type evaluator interface { + Eval(content string) bool +} +type sexp struct { + op string + args []evaluator +} + +func (s sexp) Eval(content string) bool { + switch s.op { + case "not": + if len(s.args) == 0 { + return true + } + return !s.args[0].Eval(content) + + case "and": + for _, a := range s.args { + if !a.Eval(content) { + return false + } + } + return true + + case "or": + for _, a := range s.args { + if a.Eval(content) { + return true + } + } + return false + } + return false +} + +type matcher string + +func (m matcher) Eval(content string) bool { + return strings.Contains(content, string(m)) +} diff --git a/rules_test.go b/rules_test.go new file mode 100644 index 0000000..cf25cc7 --- /dev/null +++ b/rules_test.go @@ -0,0 +1,38 @@ +package main + +import "testing" + +func TestSexp(t *testing.T) { + + sexp := sexp{ + op: "and", + args: []evaluator{ + sexp{op: "or", args: []evaluator{matcher("too"), matcher("boo")}}, + sexp{op: "not", args: []evaluator{matcher("crumble")}}, + }, + } + + if sexp.Eval("footle boolte") != true { + t.Errorf("expected true, have false") + } + + if sexp.Eval("boo crumble") != false { + t.Errorf("expected false, have true") + } +} + +func TestSexpNot(t *testing.T) { + + sexp := sexp{ + op: "not", + args: []evaluator{matcher("footle")}, + } + + if sexp.Eval("boolte tootle") != true { + t.Errorf("expected true, have false") + } + + if sexp.Eval("footle mcdootle") != false { + t.Errorf("expected false, have true") + } +}