diff --git a/checker/checker.go b/checker/checker.go index 314cb65b..5e20e5e8 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -13,6 +13,45 @@ import ( "github.com/expr-lang/expr/parser" ) +// ParseCheck parses input expression and checks its types. Also, it applies +// all provided patchers. In case of error, it returns error with a tree. +func ParseCheck(input string, config *conf.Config) (*parser.Tree, error) { + tree, err := parser.ParseWithConfig(input, config) + if err != nil { + return nil, err + } + + if len(config.Visitors) > 0 { + for i := 0; i < 1000; i++ { + more := false + for _, v := range config.Visitors { + // We need to perform types check, because some visitors may rely on + // types information available in the tree. + _, _ = Check(tree, config) + + ast.Walk(&tree.Node, v) + + if v, ok := v.(interface { + ShouldRepeat() bool + }); ok { + more = more || v.ShouldRepeat() + } + } + if !more { + break + } + } + } + _, err = Check(tree, config) + if err != nil { + return tree, err + } + + return tree, nil +} + +// Check checks types of the expression tree. It returns type of the expression +// and error if any. If config is nil, then default configuration will be used. func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) { if config == nil { config = conf.New(nil) diff --git a/expr.go b/expr.go index 83e0a167..8c619e1c 100644 --- a/expr.go +++ b/expr.go @@ -13,7 +13,6 @@ import ( "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/optimizer" - "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/patcher" "github.com/expr-lang/expr/vm" ) @@ -206,33 +205,7 @@ func Compile(input string, ops ...Option) (*vm.Program, error) { } config.Check() - tree, err := parser.ParseWithConfig(input, config) - if err != nil { - return nil, err - } - - if len(config.Visitors) > 0 { - for i := 0; i < 1000; i++ { - more := false - for _, v := range config.Visitors { - // We need to perform types check, because some visitors may rely on - // types information available in the tree. - _, _ = checker.Check(tree, config) - - ast.Walk(&tree.Node, v) - - if v, ok := v.(interface { - ShouldRepeat() bool - }); ok { - more = more || v.ShouldRepeat() - } - } - if !more { - break - } - } - } - _, err = checker.Check(tree, config) + tree, err := checker.ParseCheck(input, config) if err != nil { return nil, err }