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)) }
func simplifyOptional(p *ast.Pattern) *ast.Pattern { if isEmpty(p) { return ast.NewEmpty() } return ast.NewOptional(p) }