From cc736e9aedcac84730abbf6085f62b58fd0cffad Mon Sep 17 00:00:00 2001 From: debugtalk Date: Sun, 3 Oct 2021 20:15:55 +0800 Subject: [PATCH] feat: parseFunctionArguments --- parser.go | 41 +++++++++++++++++++++++++++++++++-------- parser_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/parser.go b/parser.go index c47be9f3..71617b54 100644 --- a/parser.go +++ b/parser.go @@ -78,9 +78,9 @@ func parseData(raw interface{}, variablesMapping map[string]interface{}) interfa } const ( - regexVariable = `[a-zA-Z_]\w*` // variable name should start with a letter or underscore - regexFunctionName = `[a-zA-Z_]\w*` // function name should start with a letter or underscore - regexNumber = `-?\d+(\.\d+)?` // match number, e.g. 123, -123, 1.23, -1.23 + regexVariable = `[a-zA-Z_]\w*` // variable name should start with a letter or underscore + regexFunctionName = `[a-zA-Z_]\w*` // function name should start with a letter or underscore + regexNumber = `^-?\d+(\.\d+)?$` // match number, e.g. 123, -123, 1.23, -1.23 ) var ( @@ -233,12 +233,10 @@ func callFunc(funcName string, arguments ...interface{}) (interface{}, error) { var eval = goval.NewEvaluator() // literalEval parse string to number if possible -// e.g. "123" => 123 -// "1.23" => 1.23 -// "abc" => "abc" -// "$var" => "$var" func literalEval(raw string) (interface{}, error) { - // check if raw is a number + raw = strings.TrimSpace(raw) + + // return raw string if not number if !regexCompileNumber.Match([]byte(raw)) { return raw, nil } @@ -246,7 +244,34 @@ func literalEval(raw string) (interface{}, error) { // eval string to number result, err := eval.Evaluate(raw, nil, nil) if err != nil { + log.Printf("[literalEval] eval %s error: %s", raw, err.Error()) return raw, err } return result, nil } + +func parseFunctionArguments(argsStr string) ([]interface{}, error) { + argsStr = strings.TrimSpace(argsStr) + if argsStr == "" { + return []interface{}{}, nil + } + + // split arguments by comma + args := strings.Split(argsStr, ",") + arguments := make([]interface{}, len(args)) + for index, arg := range args { + arg = strings.TrimSpace(arg) + if arg == "" { + continue + } + + // parse argument to number if possible + arg, err := literalEval(arg) + if err != nil { + return nil, err + } + arguments[index] = arg + } + + return arguments, nil +} diff --git a/parser_test.go b/parser_test.go index 92190bf9..2d3e4063 100644 --- a/parser_test.go +++ b/parser_test.go @@ -326,7 +326,11 @@ func TestLiteralEval(t *testing.T) { {"-123", -123}, {"-1.23", -1.23}, {"abc", "abc"}, + {" a bc ", "a bc"}, + {" a $bc ", "a $bc"}, {"$var", "$var"}, + {" $var ", "$var"}, + {" $var1 ", "$var1"}, {"", ""}, } @@ -340,3 +344,33 @@ func TestLiteralEval(t *testing.T) { } } } + +func TestParseFunctionArguments(t *testing.T) { + testData := []struct { + expr string + expect interface{} + }{ + {"", []interface{}{}}, + {"123", []interface{}{123}}, + {"1.23", []interface{}{1.23}}, + {"-123", []interface{}{-123}}, + {"-1.23", []interface{}{-1.23}}, + {"abc", []interface{}{"abc"}}, + {"$var", []interface{}{"$var"}}, + {"1,2", []interface{}{1, 2}}, + {"1,2.3", []interface{}{1, 2.3}}, + {"1, -2.3", []interface{}{1, -2.3}}, + {"1,,2", []interface{}{1, nil, 2}}, + {" $var1 , 2 ", []interface{}{"$var1", 2}}, + } + + for _, data := range testData { + value, err := parseFunctionArguments(data.expr) + if !assert.Nil(t, err) { + t.Fail() + } + if !assert.Equal(t, data.expect, value) { + t.Fail() + } + } +}