github.com/bytedance/go-tagexpr/v2@v2.9.8/expr.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 "bytes" 19 "context" 20 "fmt" 21 "os" 22 23 "github.com/andeya/goutil" 24 ) 25 26 // Expr expression 27 type Expr struct { 28 expr ExprNode 29 } 30 31 // parseExpr parses the expression. 32 func parseExpr(expr string) (*Expr, error) { 33 e := newGroupExprNode() 34 p := &Expr{ 35 expr: e, 36 } 37 s := expr 38 err := p.parseExprNode(&s, e) 39 if err != nil { 40 return nil, err 41 } 42 sortPriority(e) 43 return p, nil 44 } 45 func (p *Expr) parseExprNode(expr *string, e ExprNode) error { 46 trimLeftSpace(expr) 47 if *expr == "" { 48 return nil 49 } 50 operand := p.readSelectorExprNode(expr) 51 if operand == nil { 52 operand = p.readRangeKvExprNode(expr) 53 if operand == nil { 54 var subExprNode *string 55 operand, subExprNode = readGroupExprNode(expr) 56 if operand != nil { 57 err := p.parseExprNode(subExprNode, operand) 58 if err != nil { 59 return err 60 } 61 } else { 62 operand = p.parseOperand(expr) 63 } 64 } 65 } 66 if operand == nil { 67 return fmt.Errorf("syntax error: %q", *expr) 68 } 69 trimLeftSpace(expr) 70 operator := p.parseOperator(expr) 71 if operator == nil { 72 e.SetRightOperand(operand) 73 operand.SetParent(e) 74 return nil 75 } 76 if _, ok := e.(*groupExprNode); ok { 77 operator.SetLeftOperand(operand) 78 operand.SetParent(operator) 79 e.SetRightOperand(operator) 80 operator.SetParent(e) 81 } else { 82 operator.SetParent(e.Parent()) 83 operator.Parent().SetRightOperand(operator) 84 operator.SetLeftOperand(e) 85 e.SetParent(operator) 86 e.SetRightOperand(operand) 87 operand.SetParent(e) 88 } 89 return p.parseExprNode(expr, operator) 90 } 91 92 func (p *Expr) parseOperand(expr *string) (e ExprNode) { 93 for _, fn := range funcList { 94 if e = fn(p, expr); e != nil { 95 return e 96 } 97 } 98 if e = readStringExprNode(expr); e != nil { 99 return e 100 } 101 if e = readDigitalExprNode(expr); e != nil { 102 return e 103 } 104 if e = readBoolExprNode(expr); e != nil { 105 return e 106 } 107 if e = readNilExprNode(expr); e != nil { 108 return e 109 } 110 return nil 111 } 112 113 func (*Expr) parseOperator(expr *string) (e ExprNode) { 114 s := *expr 115 if len(s) < 2 { 116 return nil 117 } 118 defer func() { 119 if e != nil && *expr == s { 120 *expr = (*expr)[2:] 121 } 122 }() 123 a := s[:2] 124 switch a { 125 // case "<<": 126 // case ">>": 127 // case "&^": 128 case "||": 129 return newOrExprNode() 130 case "&&": 131 return newAndExprNode() 132 case "==": 133 return newEqualExprNode() 134 case ">=": 135 return newGreaterEqualExprNode() 136 case "<=": 137 return newLessEqualExprNode() 138 case "!=": 139 return newNotEqualExprNode() 140 } 141 defer func() { 142 if e != nil { 143 *expr = (*expr)[1:] 144 } 145 }() 146 switch a[0] { 147 // case '&': 148 // case '|': 149 // case '^': 150 case '+': 151 return newAdditionExprNode() 152 case '-': 153 return newSubtractionExprNode() 154 case '*': 155 return newMultiplicationExprNode() 156 case '/': 157 return newDivisionExprNode() 158 case '%': 159 return newRemainderExprNode() 160 case '<': 161 return newLessExprNode() 162 case '>': 163 return newGreaterExprNode() 164 } 165 return nil 166 } 167 168 // run calculates the value of expression. 169 func (p *Expr) run(field string, tagExpr *TagExpr) interface{} { 170 return p.expr.Run(context.Background(), field, tagExpr) 171 } 172 173 /** 174 * Priority: 175 * () ! bool float64 string nil 176 * * / % 177 * + - 178 * < <= > >= 179 * == != 180 * && 181 * || 182 **/ 183 184 func sortPriority(e ExprNode) { 185 printExprNode(e) 186 for subSortPriority(e.RightOperand(), false) { 187 printExprNode(e) 188 } 189 } 190 191 func subSortPriority(e ExprNode, isLeft bool) bool { 192 if e == nil { 193 return false 194 } 195 leftChanged := subSortPriority(e.LeftOperand(), true) 196 rightChanged := subSortPriority(e.RightOperand(), false) 197 if getPriority(e) > getPriority(e.LeftOperand()) { 198 printf("before:\n") 199 printExprNode(e) 200 leftOperandToParent(e, isLeft) 201 printf("after:\n") 202 printExprNode(e.Parent()) 203 return true 204 } 205 return leftChanged || rightChanged 206 } 207 208 func leftOperandToParent(e ExprNode, isLeft bool) { 209 le := e.LeftOperand() 210 if le == nil { 211 return 212 } 213 p := e.Parent() 214 le.SetParent(p) 215 if p != nil { 216 if isLeft { 217 p.SetLeftOperand(le) 218 } else { 219 p.SetRightOperand(le) 220 } 221 } 222 e.SetParent(le) 223 e.SetLeftOperand(le.RightOperand()) 224 le.RightOperand().SetParent(e) 225 le.SetRightOperand(e) 226 } 227 228 func getPriority(e ExprNode) (i int) { 229 // defer func() { 230 // printf("expr:%T %d\n", e, i) 231 // }() 232 switch e.(type) { 233 default: // () ! bool float64 string nil 234 return 7 235 case *multiplicationExprNode, *divisionExprNode, *remainderExprNode: // * / % 236 return 6 237 case *additionExprNode, *subtractionExprNode: // + - 238 return 5 239 case *lessExprNode, *lessEqualExprNode, *greaterExprNode, *greaterEqualExprNode: // < <= > >= 240 return 4 241 case *equalExprNode, *notEqualExprNode: // == != 242 return 3 243 case *andExprNode: // && 244 return 2 245 case *orExprNode: // || 246 return 1 247 } 248 } 249 250 // ExprNode expression interface 251 type ExprNode interface { 252 SetParent(ExprNode) 253 Parent() ExprNode 254 LeftOperand() ExprNode 255 RightOperand() ExprNode 256 SetLeftOperand(ExprNode) 257 SetRightOperand(ExprNode) 258 String() string 259 Run(context.Context, string, *TagExpr) interface{} 260 } 261 262 // var _ ExprNode = new(exprBackground) 263 264 type exprBackground struct { 265 parent ExprNode 266 leftOperand ExprNode 267 rightOperand ExprNode 268 } 269 270 func (eb *exprBackground) SetParent(e ExprNode) { 271 eb.parent = e 272 } 273 274 func (eb *exprBackground) Parent() ExprNode { 275 return eb.parent 276 } 277 278 func (eb *exprBackground) LeftOperand() ExprNode { 279 return eb.leftOperand 280 } 281 282 func (eb *exprBackground) RightOperand() ExprNode { 283 return eb.rightOperand 284 } 285 286 func (eb *exprBackground) SetLeftOperand(left ExprNode) { 287 eb.leftOperand = left 288 } 289 290 func (eb *exprBackground) SetRightOperand(right ExprNode) { 291 eb.rightOperand = right 292 } 293 294 func (*exprBackground) Run(context.Context, string, *TagExpr) interface{} { return nil } 295 296 var debugSwitch = goutil.IsGoTest() 297 298 func printf(format string, a ...interface{}) { 299 if debugSwitch { 300 fmt.Fprintf(os.Stderr, format, a...) 301 } 302 } 303 304 func printExprNode(node ExprNode) { 305 if node == nil { 306 return 307 } 308 tail := true 309 if node.Parent() != nil { 310 tail = node == node.Parent().RightOperand() 311 } 312 printf("%s\n\n", formatExprNode(node, 0, tail)) 313 } 314 315 func formatExprNode(node ExprNode, level int, tail bool) []byte { 316 var b bytes.Buffer 317 if node == nil { 318 } else { 319 b.Write(formatExprNode(node.LeftOperand(), level+1, false)) 320 321 b.Write(bytes.Repeat([]byte(" "), level)) 322 if tail { 323 b.Write([]byte("└── ")) 324 } else { 325 b.Write([]byte("┌── ")) 326 } 327 328 b.Write([]byte(node.String())) 329 b.Write([]byte("\n")) 330 331 b.Write(formatExprNode(node.RightOperand(), level+1, true)) 332 } 333 return b.Bytes() 334 }