parser improvement

This commit is contained in:
Qiu Jian
2018-10-18 17:52:08 +08:00
parent bf7acaf5e1
commit 3fabccaf71
2 changed files with 33 additions and 8 deletions

View File

@@ -20,6 +20,8 @@ var (
ErrInvalidOp = errors.New("invalid operation")
ErrFieldNotFound = errors.New("field not found")
ErrOutOfIndex = errors.New("out of index")
ErrFuncArgument = errors.New("invalid function arguments")
ErrMethodNotFound = errors.New("method not found")
)
func IsValid(exprStr string) bool {
@@ -110,23 +112,22 @@ func evalIndex(expr *ast.IndexExpr, input interface{}) (interface{}, error) {
if err != nil {
return nil, err
}
var indexI int64
switch indexV.(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
indexI = reflect.ValueOf(indexV).Int()
default:
return nil, ErrInvalidOp
}
switch X.(type) {
case []interface{}, *jsonutils.JSONArray:
arrX := getArray(X)
indexI := getInt(indexV)
if indexI >= 0 && indexI < int64(len(arrX)) {
return arrX[indexI], nil
} else {
return nil, ErrOutOfIndex
}
case *jsonutils.JSONDict:
jsonX := X.(*jsonutils.JSONDict)
field := getString(indexV)
return getJSONProperty(jsonX, field)
case string:
strX := X.(string)
indexI := getInt(indexV)
if indexI >= 0 && indexI < int64(len(strX)) {
return strX[indexI], nil
} else {
@@ -192,6 +193,18 @@ func evalCallInternal(funcV interface{}, args []interface{}) (interface{}, error
default:
return nil, ErrInvalidOp
}
case *jsonutils.JSONDict:
jsonX := caller.caller.(*jsonutils.JSONDict)
switch caller.method {
case "contains":
strArgs, err := args2Strings(args)
if err != nil {
return nil, err
}
return jsonX.Contains(strArgs...), nil
default:
return nil, ErrInvalidOp
}
default:
return nil, ErrInvalidOp
}
@@ -277,7 +290,12 @@ func evalSelectorInternal(X interface{}, identStr string) (interface{}, error) {
switch X.(type) {
case *jsonutils.JSONDict:
json := X.(*jsonutils.JSONDict)
return getJSONProperty(json, identStr)
ret, err := getJSONProperty(json, identStr)
if err == ErrFieldNotFound {
return &funcCaller{caller: X, method: identStr}, nil
} else {
return ret, err
}
case []interface{}, *jsonutils.JSONArray:
arrX := getArray(X)
ret := make([]interface{}, len(arrX))

View File

@@ -25,6 +25,10 @@ func TestAst(t *testing.T) {
{`server.disks[0].medium_type == "ssd"`, true},
{`server.disks[0].medium_type == "hdd"`, false},
{`server.os_type == "windows" && server.disks[0].medium_type == "ssd"`, true},
{`server.contains("os_type")`, true},
{`server.disks[0].contains("medium_type")`, true},
{`server.disk[0].contains("medium_type")`, true},
{`server.disks[0].contains("backend")`, false},
}
for _, c := range cases {
@@ -76,6 +80,7 @@ func TestEval2(t *testing.T) {
want bool
}{
{`server.os_type == "Linux"`, true},
{`server["os_type"] == "Linux"`, true},
{`server.vmem_size > 2048`, false},
{`server.hypervisor.in("kvm", "aliyun")`, true},
{`server.disable_delete`, false},
@@ -130,6 +135,8 @@ func TestEval3(t *testing.T) {
{`server.disk.medium == "hdd"`, true},
{`server.disk.medium == "hybrid"`, false},
{`server.disk.medium.contains("ssd")`, true},
{`server.disk[0]["medium"] == "hdd"`, true},
{`server["disk"][0]["medium"] == "hdd"`, true},
}
for _, c := range cases {