github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/exp07.go (about)

     1  package expressions
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/lmorg/murex/lang/expressions/primitives"
     9  	"github.com/lmorg/murex/lang/expressions/symbols"
    10  	"github.com/lmorg/murex/lang/types"
    11  )
    12  
    13  func expEqualFunc(tree *ParserT) (*primitives.DataType, error) {
    14  	left, right, err := tree.getLeftAndRightSymbols()
    15  	if err != nil {
    16  		return nil, err
    17  	}
    18  
    19  	lv, rv, err := compareTypes(tree, left, right)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	return primitives.NewPrimitive(primitives.Boolean, lv == rv), nil
    25  }
    26  
    27  func expEqualTo(tree *ParserT) error {
    28  	dt, err := expEqualFunc(tree)
    29  	if err != nil {
    30  		return err
    31  	}
    32  
    33  	return tree.foldAst(&astNodeT{
    34  		key: symbols.Boolean,
    35  		pos: tree.ast[tree.astPos].pos,
    36  		dt:  dt,
    37  	})
    38  }
    39  
    40  func expNotEqualTo(tree *ParserT) error {
    41  	dt, err := expEqualFunc(tree)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	dt.NotValue()
    47  
    48  	return tree.foldAst(&astNodeT{
    49  		key: symbols.Boolean,
    50  		pos: tree.ast[tree.astPos].pos,
    51  		dt:  dt,
    52  	})
    53  }
    54  
    55  func expLike(tree *ParserT, eq bool) error {
    56  	leftNode, rightNode, err := tree.getLeftAndRightSymbols()
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	left, err := leftNode.dt.GetValue()
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	right, err := rightNode.dt.GetValue()
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	lv, rv := left.Value, right.Value
    72  	// convert to number, if possible
    73  	if left.Primitive == primitives.String {
    74  		if v, err := types.ConvertGoType(left.Value, types.Number); err == nil {
    75  			lv = v
    76  		}
    77  	}
    78  	if right.Primitive == primitives.String {
    79  		if v, err := types.ConvertGoType(right.Value, types.Number); err == nil {
    80  			rv = v
    81  		}
    82  	}
    83  
    84  	// convert to string
    85  	lv, err = types.ConvertGoType(lv, types.String)
    86  	if err != nil {
    87  		return raiseError(tree.expression, tree.currentSymbol(), 0, err.Error())
    88  	}
    89  	rv, err = types.ConvertGoType(rv, types.String)
    90  	if err != nil {
    91  		return raiseError(tree.expression, tree.currentSymbol(), 0, err.Error())
    92  	}
    93  
    94  	// trim and lowercase string
    95  	lv = strings.TrimSpace(strings.ToLower(lv.(string)))
    96  	rv = strings.TrimSpace(strings.ToLower(rv.(string)))
    97  
    98  	return tree.foldAst(&astNodeT{
    99  		key: symbols.Boolean,
   100  		pos: tree.ast[tree.astPos].pos,
   101  		dt:  primitives.NewPrimitive(primitives.Boolean, (lv == rv) == eq),
   102  	})
   103  }
   104  
   105  func expRegexp(tree *ParserT, eq bool) error {
   106  	leftNode, rightNode, err := tree.getLeftAndRightSymbols()
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	left, err := leftNode.dt.GetValue()
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	right, err := rightNode.dt.GetValue()
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	var lv string
   122  
   123  	if tree.StrictTypes() {
   124  		if left.Primitive != primitives.String {
   125  			return raiseError(tree.expression, leftNode, 0, fmt.Sprintf(
   126  				"left side should be %s, instead received %s",
   127  				primitives.String, left.Primitive))
   128  		}
   129  		lv = left.Value.(string)
   130  	} else {
   131  		v, err := types.ConvertGoType(left.Value, types.String)
   132  		if err != nil {
   133  			return fmt.Errorf("cannot convert left side %s into a %s: %s",
   134  				left.Primitive, primitives.String, err.Error())
   135  		}
   136  		lv = v.(string)
   137  	}
   138  
   139  	if right.Primitive != primitives.String {
   140  		return raiseError(tree.expression, rightNode, 0, fmt.Sprintf(
   141  			"right side should be a regexp expression, instead received %s",
   142  			right.Primitive))
   143  	}
   144  
   145  	rx, err := regexp.Compile(right.Value.(string))
   146  	if err != nil {
   147  		return raiseError(tree.expression, rightNode, 0, err.Error())
   148  	}
   149  
   150  	return tree.foldAst(&astNodeT{
   151  		key: symbols.Boolean,
   152  		pos: tree.ast[tree.astPos].pos,
   153  		dt:  primitives.NewPrimitive(primitives.Boolean, rx.MatchString(lv) == eq),
   154  	})
   155  }