func TestSimplifyTree(t *testing.T) { left := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewContains( ast.NewTreeNode(ast.NewStringName("C"), ast.NewZAny()), )), ) right := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewContains( ast.NewTreeNode(ast.NewStringName("D"), ast.NewZAny()), )), ) input := ast.NewAnd(left, right) expected := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewAnd( ast.NewContains( ast.NewTreeNode(ast.NewStringName("C"), ast.NewZAny()), ), ast.NewContains( ast.NewTreeNode(ast.NewStringName("D"), ast.NewZAny()), ), )), ) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestSimplify1(t *testing.T) { c := ast.NewConcat(ast.NewNot(ast.NewZAny()), ast.NewZAny()) s := NewSimplifier(c.Grammar()).Simplify(c) if !s.Equal(ast.NewNot(ast.NewZAny())) { t.Fatalf("Expected EmptySet, but got %s", s) } }
func TestSimplifyContainsFalseTreeNode(t *testing.T) { input := ast.NewContains(ast.NewTreeNode(ast.NewAnyNameExcept(ast.NewAnyName()), ast.NewZAny())) expected := ast.NewNot(ast.NewZAny()) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestSimplifyTreeNodeWithNotZanyChild(t *testing.T) { input := ast.NewTreeNode(ast.NewAnyName(), ast.NewNot(ast.NewZAny())) expected := ast.NewNot(ast.NewZAny()) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestKeyAnyName(t *testing.T) { p := ast.NewOr( ast.NewTreeNode(ast.NewNameChoice(ast.NewAnyName(), ast.NewStringName("C")), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("B"), ast.NewZAny()), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func TestNotUnreachableArray(t *testing.T) { p := ast.NewTreeNode(ast.NewAnyNameExcept(ast.NewStringName("NotC")), ast.NewTreeNode(ast.NewStringName("F"), ast.NewConcat(ast.NewZAny(), ast.NewTreeNode(ast.NewAnyName(), ast.NewZAny(), )))) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: AnyNameExcept Not Supported Error: Name: !(NotC), but got %v", gkey) } }
func TestAnyIndex(t *testing.T) { p := ast.NewTreeNode(ast.NewStringName("KeyValue"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("Key"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("Value"), ast.NewZAny()), ))) gkey, err := FieldNamesToNumbers("protonum", "ProtoNum", ProtonumDescription(), p.Grammar()) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func derivReturn(refs ast.RefLookup, p *ast.Pattern, patterns []*ast.Pattern) (*ast.Pattern, []*ast.Pattern) { typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return ast.NewNot(ast.NewZAny()), patterns case *ast.ZAny: return ast.NewZAny(), patterns case *ast.TreeNode: if Nullable(refs, patterns[0]) { return ast.NewEmpty(), patterns[1:] } return ast.NewNot(ast.NewZAny()), patterns[1:] case *ast.LeafNode: if Nullable(refs, patterns[0]) { return ast.NewEmpty(), patterns[1:] } return ast.NewNot(ast.NewZAny()), patterns[1:] case *ast.Concat: l, leftRest := derivReturn(refs, v.GetLeftPattern(), patterns) leftConcat := ast.NewConcat(l, v.GetRightPattern()) if !Nullable(refs, v.GetLeftPattern()) { return leftConcat, leftRest } r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewOr(leftConcat, r), rightRest case *ast.Or: l, leftRest := derivReturn(refs, v.GetLeftPattern(), patterns) r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewOr(l, r), rightRest case *ast.And: l, leftRest := derivReturn(refs, v.GetLeftPattern(), patterns) r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewAnd(l, r), rightRest case *ast.Interleave: l, leftRest := derivReturn(refs, v.GetLeftPattern(), patterns) r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewOr(ast.NewInterleave(l, v.GetRightPattern()), ast.NewInterleave(r, v.GetLeftPattern())), rightRest case *ast.ZeroOrMore: c, rest := derivReturn(refs, v.GetPattern(), patterns) return ast.NewConcat(c, p), rest case *ast.Reference: return derivReturn(refs, refs[v.GetName()], patterns) case *ast.Not: c, rest := derivReturn(refs, v.GetPattern(), patterns) return ast.NewNot(c), rest case *ast.Contains: return derivReturn(refs, ast.NewConcat(ast.NewZAny(), ast.NewConcat(v.GetPattern(), ast.NewZAny())), patterns) case *ast.Optional: return derivReturn(refs, ast.NewOr(v.GetPattern(), ast.NewEmpty()), patterns) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }
func TestTopsyTurvy(t *testing.T) { p := ast.NewTreeNode(ast.NewAnyName(), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny())) gkey, err := FieldNamesToNumbers("protonum", "TopsyTurvy", ProtonumDescription(), p.Grammar()) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func simplifyContains(p *ast.Pattern) *ast.Pattern { if isEmpty(p) || isZany(p) { return ast.NewZAny() } if isNotZany(p) { return p } return ast.NewContains(p) }
func TestSimplifyFalseLeaf(t *testing.T) { input := combinator.Value(funcs.And(funcs.StringEq(funcs.StringVar(), funcs.StringConst("a")), funcs.StringEq(funcs.StringVar(), funcs.StringConst("b")))) expected := ast.NewNot(ast.NewZAny()) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestKeyOr(t *testing.T) { p := ast.NewOr( ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("B"), ast.NewZAny()), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) if gkey.GetTopPattern().GetOr().GetLeftPattern().GetTreeNode().GetName().GetName().GetUintValue() != 1 { t.Fatalf("expected field 1, but got %v", gkey) } if gkey.GetTopPattern().GetOr().GetRightPattern().GetTreeNode().GetName().GetName().GetUintValue() != 2 { t.Fatalf("expected field 2, but got %v", gkey) } }
func newList(nameOrPattern *NameOrPattern) *ast.Pattern { regexStr, nullable, err := listToRegex(nameOrPattern) if err != nil { return ast.NewNot(ast.NewZAny()) } val := combinator.Value(&list{nil, funcs.StringVar(), funcs.StringConst("^" + regexStr + "$")}) if !nullable { return val } return ast.NewOr(val, ast.NewEmpty()) }
func TestKeyAnyArrayIndex(t *testing.T) { p := ast.NewConcat( ast.NewZAny(), ast.NewTreeNode(ast.NewStringName("E"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("B"), ast.NewZAny()), ), ), ), ast.NewZAny(), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func TestRepeatedMessageWithNoFieldsOfTypeMessage(t *testing.T) { p := ast.NewConcat( ast.NewZAny(), ast.NewTreeNode(ast.NewStringName("KeyValue"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("Key"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("Value"), ast.NewZAny()), ), ), ), ast.NewZAny(), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("protonum", "ProtoNum", ProtonumDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func derivCall(refs map[string]*ast.Pattern, getFunc func(*ast.Expr) funcs.Bool, p *ast.Pattern) []*ifExpr { typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return []*ifExpr{} case *ast.ZAny: return []*ifExpr{} case *ast.TreeNode: b := nameexpr.NameToFunc(v.GetName()) return []*ifExpr{{b, v.GetPattern(), ast.NewNot(ast.NewZAny())}} case *ast.LeafNode: b := getFunc(v.GetExpr()) return []*ifExpr{{b, ast.NewEmpty(), ast.NewNot(ast.NewZAny())}} case *ast.Concat: l := derivCall(refs, getFunc, v.GetLeftPattern()) if !interp.Nullable(refs, v.GetLeftPattern()) { return l } r := derivCall(refs, getFunc, v.GetRightPattern()) return append(l, r...) case *ast.Or: return derivCall2(refs, getFunc, v.GetLeftPattern(), v.GetRightPattern()) case *ast.And: return derivCall2(refs, getFunc, v.GetLeftPattern(), v.GetRightPattern()) case *ast.Interleave: return derivCall2(refs, getFunc, v.GetLeftPattern(), v.GetRightPattern()) case *ast.ZeroOrMore: return derivCall(refs, getFunc, v.GetPattern()) case *ast.Reference: return derivCall(refs, getFunc, refs[v.GetName()]) case *ast.Not: return derivCall(refs, getFunc, v.GetPattern()) case *ast.Contains: return derivCall(refs, getFunc, ast.NewConcat(ast.NewZAny(), ast.NewConcat(v.GetPattern(), ast.NewZAny()))) case *ast.Optional: return derivCall(refs, getFunc, ast.NewOr(v.GetPattern(), ast.NewEmpty())) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }
func TestKeyRecursive(t *testing.T) { p := ast.NewOr( ast.NewTreeNode(ast.NewStringName("C"), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func TestKeyLeftRecursive(t *testing.T) { p := ast.NewOr( ast.NewReference("a"), ast.NewTreeNode(ast.NewStringName("C"), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ) g := p.Grammar().AddRef("a", ast.NewReference("main")) gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) if gkey.GetTopPattern().GetOr().GetRightPattern().GetOr().GetLeftPattern().GetTreeNode().GetName().GetName().GetUintValue() != 3 { t.Fatalf("expected field 3, but got %v", gkey) } check(t, gkey) }
func simplifyOr(refs ast.RefLookup, p1, p2 *ast.Pattern, record bool) *ast.Pattern { if isNotZany(p1) { return p2 } if isNotZany(p2) { return p1 } if isZany(p1) || isZany(p2) { return ast.NewZAny() } if isEmpty(p1) && Nullable(refs, p2) { return p2 } if isEmpty(p2) && Nullable(refs, p1) { return p1 } if p1.GetLeafNode() != nil && p2.GetLeafNode() != nil { expr1, err1 := compose.ConvertBuiltInIntoFunction(p1.GetLeafNode().GetExpr()) expr2, err2 := compose.ConvertBuiltInIntoFunction(p2.GetLeafNode().GetExpr()) if err1 == nil && err2 == nil { return ast.NewLeafNode(ast.NewFunction("or", expr1, expr2)) } } left := getOrs(p1) right := getOrs(p2) list := append(left, right...) list = ast.Set(list) list = simplifyChildren(list, func(left, right *ast.Pattern) *ast.Pattern { return simplifyOr(refs, left, right, record) }, record) ast.Sort(list) var p *ast.Pattern = list[0] for i := range list { if i == 0 { continue } p = ast.NewOr(p, list[i]) } return p }
func (this *simplifier) OptimizeForRecord() Simplifier { this.record = true return this } func checkRef(refs ast.RefLookup, p *ast.Pattern) *ast.Pattern { for name, rpat := range refs { if rpat.Equal(p) { return ast.NewReference(name) } } return p } var emptyset = ast.NewNot(ast.NewZAny()) func (this *simplifier) simplify(p *ast.Pattern, top bool) *ast.Pattern { cRef := func(cp *ast.Pattern) *ast.Pattern { if top { return cp } return checkRef(this.refs, cp) } cachesimp := func(sp *ast.Pattern) *ast.Pattern { if _, ok := this.cache[sp]; ok { return sp } s := this.simplify(sp, false) this.cache[s] = struct{}{} return s
func TestUnreachable(t *testing.T) { p := ast.NewTreeNode(ast.NewStringName("NotC"), ast.NewTreeNode(ast.NewStringName("C"), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()))) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: Unknown Field Error: Name: NotC, Msg: Debug, but got %v", gkey) } }
func derivCall(refs ast.RefLookup, p *ast.Pattern, label parser.Value) ([]*ast.Pattern, error) { typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return []*ast.Pattern{}, nil case *ast.ZAny: return []*ast.Pattern{}, nil case *ast.TreeNode: b := nameexpr.NameToFunc(v.GetName()) f, err := compose.NewBoolFunc(b) if err != nil { return nil, err } eval, err := f.Eval(label) if err != nil { return nil, err } if eval { return []*ast.Pattern{v.GetPattern()}, nil } return []*ast.Pattern{ast.NewNot(ast.NewZAny())}, nil case *ast.LeafNode: b, err := compose.NewBool(v.GetExpr()) if err != nil { return nil, err } f, err := compose.NewBoolFunc(b) if err != nil { return nil, err } eval, err := f.Eval(label) if err != nil { return nil, err } if eval { return []*ast.Pattern{ast.NewEmpty()}, nil } return []*ast.Pattern{ast.NewNot(ast.NewZAny())}, nil case *ast.Concat: l, err := derivCall(refs, v.GetLeftPattern(), label) if err != nil { return nil, err } if !Nullable(refs, v.GetLeftPattern()) { return l, nil } r, err := derivCall(refs, v.GetRightPattern(), label) if err != nil { return nil, err } return append(l, r...), nil case *ast.Or: return derivCall2(refs, v.GetLeftPattern(), v.GetRightPattern(), label) case *ast.And: return derivCall2(refs, v.GetLeftPattern(), v.GetRightPattern(), label) case *ast.Interleave: return derivCall2(refs, v.GetLeftPattern(), v.GetRightPattern(), label) case *ast.ZeroOrMore: return derivCall(refs, v.GetPattern(), label) case *ast.Reference: return derivCall(refs, refs[v.GetName()], label) case *ast.Not: return derivCall(refs, v.GetPattern(), label) case *ast.Contains: return derivCall(refs, ast.NewConcat(ast.NewZAny(), ast.NewConcat(v.GetPattern(), ast.NewZAny())), label) case *ast.Optional: return derivCall(refs, ast.NewOr(v.GetPattern(), ast.NewEmpty()), label) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }
func TestRecursiveKnotElbow(t *testing.T) { p := ast.NewOr(ast.NewTreeNode(ast.NewAnyName(), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("Elbow"), ast.NewZAny())) gkey, err := FieldNamesToNumbers("protonum", "Knot", ProtonumDescription(), p.Grammar()) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func TestSimplify2(t *testing.T) { s := NewSimplifier(andNameTelephonePerson.Grammar()).Simplify(andNameTelephonePerson["main"]) if s.Equal(ast.NewNot(ast.NewZAny())) { t.Fatalf("Did not expected EmptySet") } }
// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mem import ( "github.com/katydid/katydid/relapse/ast" ) var ( zipIgnoreSet = []*ast.Pattern{ ast.NewZAny(), ast.NewNot(ast.NewZAny()), } zignoreb = []bool{ true, false, } ) func zip(patterns []*ast.Pattern) ([]*ast.Pattern, []int) { set := ast.Set(patterns) ast.Sort(set) if index := ast.Index(set, zipIgnoreSet[0]); index != -1 { set = ast.Remove(set, index) }