func nullables(refs map[string]*ast.Pattern, patterns []*ast.Pattern) bitset { nulls := newBitSet(len(patterns)) for i, p := range patterns { nulls.set(i, interp.Nullable(refs, p)) } return nulls }
func (this *Mem) calcAccepts(upto int) { for i := len(this.Accept); i <= upto; i++ { patterns := this.patterns[i] if len(patterns) != 1 { this.Accept = append(this.Accept, false) } else { this.Accept = append(this.Accept, interp.Nullable(this.refs, patterns[0])) } } }
func derivReturn(refs map[string]*ast.Pattern, p *ast.Pattern, nullable []bool) (*ast.Pattern, []bool) { typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return ast.NewNot(ast.NewZAny()), nullable case *ast.ZAny: return ast.NewZAny(), nullable case *ast.TreeNode: if nullable[0] { return ast.NewEmpty(), nullable[1:] } return ast.NewNot(ast.NewZAny()), nullable[1:] case *ast.LeafNode: if nullable[0] { return ast.NewEmpty(), nullable[1:] } return ast.NewNot(ast.NewZAny()), nullable[1:] case *ast.Concat: l, leftRest := derivReturn(refs, v.GetLeftPattern(), nullable) leftConcat := ast.NewConcat(l, v.GetRightPattern()) if !interp.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(), nullable) r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewOr(l, r), rightRest case *ast.And: l, leftRest := derivReturn(refs, v.GetLeftPattern(), nullable) r, rightRest := derivReturn(refs, v.GetRightPattern(), leftRest) return ast.NewAnd(l, r), rightRest case *ast.Interleave: l, leftRest := derivReturn(refs, v.GetLeftPattern(), nullable) 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(), nullable) return ast.NewConcat(c, p), rest case *ast.Reference: return derivReturn(refs, refs[v.GetName()], nullable) case *ast.Not: c, rest := derivReturn(refs, v.GetPattern(), nullable) return ast.NewNot(c), rest case *ast.Contains: return derivReturn(refs, ast.NewConcat(ast.NewZAny(), ast.NewConcat(v.GetPattern(), ast.NewZAny())), nullable) case *ast.Optional: return derivReturn(refs, ast.NewOr(v.GetPattern(), ast.NewEmpty()), nullable) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }
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)) }