Пример #1
0
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))
}
Пример #2
0
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
	}
	simp := func(sp *ast.Pattern) *ast.Pattern {
		return this.simplify(sp, false)
	}
	typ := p.GetValue()
	switch v := typ.(type) {
	case *ast.Empty:
		return p
	case *ast.TreeNode:
		child := cachesimp(v.GetPattern())
		if isNotZany(child) {
			return emptyset
		}
		name := v.GetName()
		b := nameexpr.NameToFunc(v.GetName())
		if funcs.IsFalse(b) {
			return emptyset
		}
		if funcs.IsTrue(b) {
			name = ast.NewAnyName()
		}
		return cRef(ast.NewTreeNode(name, child))
	case *ast.LeafNode:
		b, err := compose.NewBool(v.GetExpr())
		if err != nil {
			//Don't simplify if there is an error to keep this function signature simple.
			return p
		}
		if funcs.IsFalse(b) {
			return emptyset
		}
		return p
	case *ast.Concat:
		return cRef(simplifyConcat(
			simp(v.GetLeftPattern()),
			simp(v.GetRightPattern()),
		))
	case *ast.Or:
		return cRef(simplifyOr(this.refs,
			simp(v.GetLeftPattern()),
			simp(v.GetRightPattern()),
			this.record,
		))
	case *ast.And:
		return cRef(simplifyAnd(this.refs,
			simp(v.GetLeftPattern()),
			simp(v.GetRightPattern()),
			this.record,
		))
	case *ast.ZeroOrMore:
		return cRef(simplifyZeroOrMore(simp(v.GetPattern())))
	case *ast.Reference:
		return p
	case *ast.Not:
		return cRef(simplifyNot(simp(v.GetPattern())))
	case *ast.ZAny:
		return p
	case *ast.Contains:
		return cRef(simplifyContains(simp(v.GetPattern())))
	case *ast.Optional:
		return simplifyOptional(simp(v.GetPattern()))
	case *ast.Interleave:
		return cRef(simplifyInterleave(this.refs,
			cachesimp(v.GetLeftPattern()),
			cachesimp(v.GetRightPattern()),
		))
	}
	panic(fmt.Sprintf("unknown pattern typ %T", typ))
}
Пример #3
0
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))
}