示例#1
0
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)
	}
}
示例#2
0
func simplifyChildren(children []*ast.Pattern, op func(left, right *ast.Pattern) *ast.Pattern, record bool) []*ast.Pattern {
	if len(children) == 0 || len(children) == 1 {
		return children
	}

	if record {
		c0 := children[0].GetContains().GetPattern().GetTreeNode()
		c1 := children[1].GetContains().GetPattern().GetTreeNode()
		if c0 != nil && c1 != nil {
			if c0.GetName().Equal(c1.GetName()) {
				newchild := ast.NewContains(ast.NewTreeNode(c0.GetName(), op(c0.GetPattern(), c1.GetPattern())))
				children[1] = newchild
				return simplifyChildren(children[1:], op, record)
			}
		}
	}

	t0 := children[0].TreeNode
	t1 := children[1].TreeNode
	if t0 != nil && t1 != nil {
		if t0.GetName().Equal(t1.GetName()) {
			newchild := ast.NewTreeNode(t0.GetName(), op(t0.GetPattern(), t1.GetPattern()))
			children[1] = newchild
			return simplifyChildren(children[1:], op, record)
		}
	}

	return append([]*ast.Pattern{children[0]}, simplifyChildren(children[1:], op, record)...)
}
示例#3
0
func simplifyContains(p *ast.Pattern) *ast.Pattern {
	if isEmpty(p) || isZany(p) {
		return ast.NewZAny()
	}
	if isNotZany(p) {
		return p
	}
	return ast.NewContains(p)
}
示例#4
0
func TestSimplifyRecordLeaf1(t *testing.T) {
	input := ast.NewAnd(
		ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.Contains(funcs.StringVar(), funcs.StringConst("a"))))),
		ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.Contains(funcs.StringVar(), funcs.StringConst("b"))))),
	)
	t.Logf("input: %v", input)
	expected := ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.And(
		funcs.Contains(funcs.StringVar(), funcs.StringConst("a")),
		funcs.Contains(funcs.StringVar(), funcs.StringConst("b")),
	))))
	output := NewSimplifier(input.Grammar()).OptimizeForRecord().Simplify(input)
	expected.Format()
	output.Format()
	t.Logf("%v", output)
	if !expected.Equal(output) {
		t.Fatalf("expected %v, but got %v", expected, output)
	}
}
示例#5
0
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)
	}
}
示例#6
0
func (this *nameToNumber) translate(context *context, p *ast.Pattern) (*ast.Pattern, error) {
	typ := p.GetValue()
	switch v := typ.(type) {
	case *ast.Empty, *ast.LeafNode, *ast.ZAny:
		return p, nil
	case *ast.TreeNode:
		return this.translateName(context, v.GetName(), v.GetPattern())
	case *ast.Concat:
		l, err1 := this.translate(context, v.GetLeftPattern())
		r, err2 := this.translate(context, v.GetRightPattern())
		return ast.NewConcat(l, r), anyErr(err1, err2)
	case *ast.Or:
		l, err1 := this.translate(context, v.GetLeftPattern())
		r, err2 := this.translate(context, v.GetRightPattern())
		return ast.NewOr(l, r), anyErr(err1, err2)
	case *ast.And:
		l, err1 := this.translate(context, v.GetLeftPattern())
		r, err2 := this.translate(context, v.GetRightPattern())
		return ast.NewAnd(l, r), anyErr(err1, err2)
	case *ast.ZeroOrMore:
		p, err := this.translate(context, v.GetPattern())
		return ast.NewZeroOrMore(p), err
	case *ast.Reference:
		c, ok := this.refs[v.GetName()]
		if !ok {
			this.refs[v.GetName()] = context
			return p, nil
		}
		if !c.Equal(context) {
			//TODO we could probably create a new reference here
			//  for every conflicting combination of msg x repeated x referece name
			return nil, &ErrDup{v.GetName(), c, context}
		}
		return p, nil
	case *ast.Not:
		p, err := this.translate(context, v.GetPattern())
		return ast.NewNot(p), err
	case *ast.Contains:
		p, err := this.translate(context, v.GetPattern())
		return ast.NewContains(p), err
	case *ast.Optional:
		p, err := this.translate(context, v.GetPattern())
		return ast.NewOptional(p), err
	case *ast.Interleave:
		l, err1 := this.translate(context, v.GetLeftPattern())
		r, err2 := this.translate(context, v.GetRightPattern())
		return ast.NewInterleave(l, r), anyErr(err1, err2)
	}
	panic(fmt.Sprintf("unknown pattern typ %T", typ))
}
示例#7
0
func simplifyConcat(p1, p2 *ast.Pattern) *ast.Pattern {
	if isNotZany(p1) || isNotZany(p2) {
		return emptyset
	}
	if p1.Concat != nil {
		return simplifyConcat(
			p1.Concat.GetLeftPattern(),
			ast.NewConcat(p1.Concat.GetRightPattern(), p2),
		)
	}
	if isEmpty(p1) {
		return p2
	}
	if isEmpty(p2) {
		return p1
	}
	if isZany(p1) && p2.Concat != nil {
		if l := p2.Concat.GetLeftPattern(); isZany(p2.Concat.GetRightPattern()) {
			return ast.NewContains(l)
		}
	}
	return ast.NewConcat(p1, p2)
}