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

     1  package expressions
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/lmorg/murex/lang/expressions/primitives"
     7  	"github.com/lmorg/murex/lang/expressions/symbols"
     8  	"github.com/lmorg/murex/utils/consts"
     9  )
    10  
    11  func (tree *ParserT) executeExpr() (*primitives.DataType, error) {
    12  	err := tree.validateExpression(true)
    13  	if err != nil {
    14  		return nil, err
    15  	}
    16  
    17  	for i := range orderOfOperations {
    18  		err = executeExpression(tree, orderOfOperations[i])
    19  		if err != nil {
    20  			return nil, err
    21  		}
    22  	}
    23  
    24  	if len(tree.ast) > 1 {
    25  		return nil, fmt.Errorf(
    26  			"expression failed to execute correctly (AST results > 1).\n%s",
    27  			consts.IssueTrackerURL)
    28  	}
    29  
    30  	return tree.ast[0].dt, nil
    31  }
    32  
    33  // To allow for extendability and developer expectations, the order of operations
    34  // will follow what is defined by (for example) C, as outlined in the following:
    35  // https://en.wikipedia.org/wiki/Order_of_operations#Programming_languages
    36  // Not all operations will be available in murex and some are likely to be added
    37  // in future versions of this package.
    38  //
    39  // Please also note that the slice below is just defining the groupings. Each
    40  // operator within the _same_ group will then be processed from left to right.
    41  // Read the `executeExpression` function further down this source file to view
    42  // every supported operator
    43  var orderOfOperations = []symbols.Exp{
    44  	// 01. Function call, scope, array/member access
    45  	// 02. (most) unary operators, sizeof and type casts (right to left)
    46  	// 03. Multiplication, division, modulo
    47  	symbols.Multiply,
    48  
    49  	// 04. Addition and subtraction
    50  	symbols.Add,
    51  
    52  	// 05. Bitwise shift left and right
    53  	// 06. Comparisons: less-than and greater-than
    54  	symbols.GreaterThan,
    55  
    56  	// 07. Comparisons: equal and not equal
    57  	symbols.EqualTo,
    58  
    59  	// 08. Bitwise AND
    60  	// 09. Bitwise exclusive OR (XOR)
    61  	// 10. Bitwise inclusive (normal) OR
    62  	// 11. Logical AND
    63  	symbols.LogicalAnd,
    64  
    65  	// 12. Logical OR
    66  	symbols.LogicalOr,
    67  
    68  	// 13. Conditional expression (ternary)
    69  	symbols.Elvis,
    70  
    71  	// 14. Assignment operators (right to left)
    72  	symbols.Assign,
    73  
    74  	// 15. Comma operator
    75  }
    76  
    77  func executeExpression(tree *ParserT, order symbols.Exp) (err error) {
    78  	for tree.astPos = 0; tree.astPos < len(tree.ast); tree.astPos++ {
    79  		node := tree.ast[tree.astPos]
    80  
    81  		if node.key < order {
    82  			continue
    83  		}
    84  
    85  		switch node.key {
    86  
    87  		// 15. Comma operator
    88  		// 14. Assignment operators (right to left)
    89  		case symbols.Assign:
    90  			err = expAssign(tree, true)
    91  		case symbols.AssignUpdate:
    92  			err = expAssign(tree, false)
    93  		case symbols.AssignAndAdd:
    94  			err = expAssignAdd(tree)
    95  		case symbols.AssignAndSubtract:
    96  			err = expAssignAndOperate(tree, _assSub)
    97  		case symbols.AssignAndDivide:
    98  			err = expAssignAndOperate(tree, _assDiv)
    99  		case symbols.AssignAndMultiply:
   100  			err = expAssignAndOperate(tree, _assMulti)
   101  		case symbols.AssignAndMerge:
   102  			err = expAssignMerge(tree)
   103  
   104  		// 13. Conditional expression (ternary)
   105  		case symbols.NullCoalescing:
   106  			err = expNullCoalescing(tree)
   107  		case symbols.Elvis:
   108  			err = expElvis(tree)
   109  
   110  		// 12. Logical OR
   111  		case symbols.LogicalOr:
   112  			err = expLogicalOr(tree)
   113  
   114  		// 11. Logical AND
   115  		case symbols.LogicalAnd:
   116  			err = expLogicalAnd(tree)
   117  
   118  		// 10. Bitwise inclusive (normal) OR
   119  		// 09. Bitwise exclusive OR (XOR)
   120  		// 08. Bitwise AND
   121  		// 07. Comparisons: equal and not equal
   122  		case symbols.EqualTo:
   123  			err = expEqualTo(tree)
   124  		case symbols.NotEqualTo:
   125  			err = expNotEqualTo(tree)
   126  		case symbols.Like:
   127  			err = expLike(tree, true)
   128  		case symbols.NotLike:
   129  			err = expLike(tree, false)
   130  		case symbols.Regexp:
   131  			err = expRegexp(tree, true)
   132  		case symbols.NotRegexp:
   133  			err = expRegexp(tree, false)
   134  
   135  		// 06. Comparisons: less-than and greater-than
   136  		case symbols.GreaterThan:
   137  			err = expGtLt(tree, _gtF, _gtS)
   138  		case symbols.GreaterThanOrEqual:
   139  			err = expGtLt(tree, _gtEqF, _gtEqS)
   140  		case symbols.LessThan:
   141  			err = expGtLt(tree, _ltF, _ltS)
   142  		case symbols.LessThanOrEqual:
   143  			err = expGtLt(tree, _ltEqF, _ltEqS)
   144  
   145  		// 05. Bitwise shift left and right
   146  		// 04. Addition and subtraction
   147  		case symbols.Add:
   148  			err = expAdd(tree)
   149  		case symbols.Subtract:
   150  			err = expSubtract(tree)
   151  		case symbols.MergeInto:
   152  			err = expMergeInto(tree)
   153  
   154  		// 03. Multiplication, division, modulo
   155  		case symbols.Multiply:
   156  			err = expMultiply(tree)
   157  		case symbols.Divide:
   158  			err = expDivide(tree)
   159  
   160  		// 02. (most) unary operators, sizeof and type casts (right to left)
   161  		// 01. Function call, scope, array/member access
   162  
   163  		default:
   164  			err = raiseError(tree.expression, node, 0, fmt.Sprintf(
   165  				"no code written to handle symbol (%s)",
   166  				consts.IssueTrackerURL))
   167  		}
   168  
   169  		if err != nil {
   170  			return err
   171  		}
   172  
   173  		tree.astPos = 0
   174  	}
   175  
   176  	return nil
   177  }