github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/spec_operand.go (about) 1 // Copyright 2019 Bytedance Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tagexpr 16 17 import ( 18 "regexp" 19 "strconv" 20 "strings" 21 ) 22 23 // --------------------------- Operand --------------------------- 24 25 type groupExprNode struct { 26 exprBackground 27 boolOpposite *bool 28 } 29 30 func newGroupExprNode() ExprNode { return &groupExprNode{} } 31 32 func readGroupExprNode(expr *string) (grp ExprNode, subExprNode *string) { 33 last, boolOpposite := getBoolOpposite(expr) 34 sptr := readPairedSymbol(&last, '(', ')') 35 if sptr == nil { 36 return nil, nil 37 } 38 *expr = last 39 e := &groupExprNode{boolOpposite: boolOpposite} 40 return e, sptr 41 } 42 43 func (ge *groupExprNode) Run(currField string, tagExpr *TagExpr) interface{} { 44 if ge.rightOperand == nil { 45 return nil 46 } 47 return realValue(ge.rightOperand.Run(currField, tagExpr), ge.boolOpposite) 48 } 49 50 type boolExprNode struct { 51 exprBackground 52 val bool 53 } 54 55 var boolRegexp = regexp.MustCompile(`^!*(true|false)([\)\],\|&!= \t]{1}|$)`) 56 57 func readBoolExprNode(expr *string) ExprNode { 58 s := boolRegexp.FindString(*expr) 59 if s == "" { 60 return nil 61 } 62 last := s[len(s)-1] 63 if last != 'e' { 64 s = s[:len(s)-1] 65 } 66 *expr = (*expr)[len(s):] 67 e := &boolExprNode{} 68 if strings.Contains(s, "t") { 69 e.val = (len(s)-4)%2 == 0 70 } else { 71 e.val = (len(s)-5)%2 == 1 72 } 73 return e 74 } 75 76 func (be *boolExprNode) Run(currField string, tagExpr *TagExpr) interface{} { return be.val } 77 78 type stringExprNode struct { 79 exprBackground 80 val interface{} 81 } 82 83 func readStringExprNode(expr *string) ExprNode { 84 last, boolOpposite := getBoolOpposite(expr) 85 sptr := readPairedSymbol(&last, '\'', '\'') 86 if sptr == nil { 87 return nil 88 } 89 *expr = last 90 e := &stringExprNode{val: realValue(*sptr, boolOpposite)} 91 return e 92 } 93 94 func (se *stringExprNode) Run(currField string, tagExpr *TagExpr) interface{} { return se.val } 95 96 type digitalExprNode struct { 97 exprBackground 98 val interface{} 99 } 100 101 var digitalRegexp = regexp.MustCompile(`^[\+\-]?\d+(\.\d+)?([\)\],\+\-\*\/%><\|&!=\^ \t\\]|$)`) 102 103 func readDigitalExprNode(expr *string) ExprNode { 104 last, boolOpposite := getBoolOpposite(expr) 105 s := digitalRegexp.FindString(last) 106 if s == "" { 107 return nil 108 } 109 if r := s[len(s)-1]; r < '0' || r > '9' { 110 s = s[:len(s)-1] 111 } 112 *expr = last[len(s):] 113 f64, _ := strconv.ParseFloat(s, 64) 114 return &digitalExprNode{val: realValue(f64, boolOpposite)} 115 } 116 117 func (de *digitalExprNode) Run(currField string, tagExpr *TagExpr) interface{} { return de.val } 118 119 type nilExprNode struct { 120 exprBackground 121 val interface{} 122 } 123 124 var nilRegexp = regexp.MustCompile(`^nil([\)\],\|&!= \t]{1}|$)`) 125 126 func readNilExprNode(expr *string) ExprNode { 127 last, boolOpposite := getBoolOpposite(expr) 128 s := nilRegexp.FindString(last) 129 if s == "" { 130 return nil 131 } 132 *expr = last[3:] 133 return &nilExprNode{val: realValue(nil, boolOpposite)} 134 } 135 136 func (ne *nilExprNode) Run(currField string, tagExpr *TagExpr) interface{} { return ne.val } 137 138 func getBoolOpposite(expr *string) (string, *bool) { 139 last := strings.TrimLeft(*expr, "!") 140 n := len(*expr) - len(last) 141 if n == 0 { 142 return last, nil 143 } 144 bol := n%2 == 1 145 return last, &bol 146 } 147 148 func realValue(v interface{}, boolOpposite *bool) interface{} { 149 if boolOpposite == nil { 150 return v 151 } 152 bol := FakeBool(v) 153 if *boolOpposite { 154 return !bol 155 } 156 return bol 157 }