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  }