Add checker.ParseCheck func

This commit is contained in:
Anton Medvedev
2024-05-18 23:13:58 +02:00
parent 0a33193f26
commit 0d07afb7ae
2 changed files with 40 additions and 28 deletions
+39
View File
@@ -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)
+1 -28
View File
@@ -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
}