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