Exemplo n.º 1
0
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))
}
Exemplo n.º 2
0
func simplifyInterleave(refs ast.RefLookup, p1, p2 *ast.Pattern) *ast.Pattern {
	if isNotZany(p1) || isNotZany(p2) {
		return emptyset
	}
	if isEmpty(p1) {
		return p2
	}
	if isEmpty(p2) {
		return p1
	}
	if isZany(p1) && isZany(p2) {
		return p1
	}
	left := getInterleaves(p1)
	right := getInterleaves(p2)
	list := append(left, right...)
	list = ast.Set(list)
	ast.Sort(list)
	var p *ast.Pattern = list[0]
	for i := range list {
		if i == 0 {
			continue
		}
		p = ast.NewInterleave(p, list[i])
	}
	return p
}
Exemplo n.º 3
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))
}