github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/docs/commands/expr.md (about) 1 # `expr` 2 3 > Expressions: mathematical, string comparisons, logical operators 4 5 ## Description 6 7 `expr` is the underlying builtin which handles all expression parsing and 8 evaluation in Murex. Though typically that would happen transparently without 9 you having to explicit call `expr`. 10 11 For a full list of operators supported exclusively in expression, see the 12 last section in this document. 13 14 ## Usage 15 16 ``` 17 expression -> <stdout> 18 19 statement (expression) 20 21 expr expression -> <stdout> 22 ``` 23 24 ## Examples 25 26 **Expressions:** 27 28 ``` 29 » 3 * (3 + 1) 30 12 31 ``` 32 33 **Statements with inlined expressions:** 34 35 Any parameter surrounded by parenthesis is first evaluated as an expression, 36 then as a string. 37 38 ``` 39 » out (3 * 2) 40 6 41 ``` 42 43 **Expressions with inlined statements:** 44 45 Functions can be inlined as a statement using `function(parameters...)` syntax. 46 47 ``` 48 » datetime(--in {now} --out {unix}) / 60 49 28339115.783333335 50 ``` 51 52 Please note that currently the only functions supported are ones who's names 53 are comprised entirely of alpha, numeric, underscore and/or exclamation marks. 54 55 **JSON array:** 56 57 ``` 58 » %[apples oranges grapes] 59 [ 60 "apples", 61 "oranges", 62 "grapes" 63 ] 64 ``` 65 66 ## Detail 67 68 ### Order of Operations 69 70 The order of operations follows the same rules as the C programming language, 71 which itself is an extension of the order of operations in mathematics, often 72 referred to as PEMDAS or MODMAS ([read more](https://en.wikipedia.org/wiki/Order_of_operations)). 73 74 The [Wikipedia article](https://en.wikipedia.org/wiki/Order_of_operations#Programming_languages) 75 summarises that order succinctly however the detailed specification is defined 76 by its implementation, as seen in the code below: 77 78 ```go 79 package expressions 80 81 import ( 82 "fmt" 83 84 "github.com/lmorg/murex/lang/expressions/primitives" 85 "github.com/lmorg/murex/lang/expressions/symbols" 86 "github.com/lmorg/murex/utils/consts" 87 ) 88 89 func (tree *ParserT) executeExpr() (*primitives.DataType, error) { 90 err := tree.validateExpression(true) 91 if err != nil { 92 return nil, err 93 } 94 95 for i := range orderOfOperations { 96 err = executeExpression(tree, orderOfOperations[i]) 97 if err != nil { 98 return nil, err 99 } 100 } 101 102 if len(tree.ast) > 1 { 103 return nil, fmt.Errorf( 104 "expression failed to execute correctly (AST results > 1).\n%s", 105 consts.IssueTrackerURL) 106 } 107 108 return tree.ast[0].dt, nil 109 } 110 111 // To allow for extendability and developer expectations, the order of operations 112 // will follow what is defined by (for example) C, as outlined in the following: 113 // https://en.wikipedia.org/wiki/Order_of_operations#Programming_languages 114 // Not all operations will be available in murex and some are likely to be added 115 // in future versions of this package. 116 // 117 // Please also note that the slice below is just defining the groupings. Each 118 // operator within the _same_ group will then be processed from left to right. 119 // Read the `executeExpression` function further down this source file to view 120 // every supported operator 121 var orderOfOperations = []symbols.Exp{ 122 // 01. Function call, scope, array/member access 123 // 02. (most) unary operators, sizeof and type casts (right to left) 124 // 03. Multiplication, division, modulo 125 symbols.Multiply, 126 127 // 04. Addition and subtraction 128 symbols.Add, 129 130 // 05. Bitwise shift left and right 131 // 06. Comparisons: less-than and greater-than 132 symbols.GreaterThan, 133 134 // 07. Comparisons: equal and not equal 135 symbols.EqualTo, 136 137 // 08. Bitwise AND 138 // 09. Bitwise exclusive OR (XOR) 139 // 10. Bitwise inclusive (normal) OR 140 // 11. Logical AND 141 symbols.LogicalAnd, 142 143 // 12. Logical OR 144 symbols.LogicalOr, 145 146 // 13. Conditional expression (ternary) 147 symbols.Elvis, 148 149 // 14. Assignment operators (right to left) 150 symbols.Assign, 151 152 // 15. Comma operator 153 } 154 155 func executeExpression(tree *ParserT, order symbols.Exp) (err error) { 156 for tree.astPos = 0; tree.astPos < len(tree.ast); tree.astPos++ { 157 node := tree.ast[tree.astPos] 158 159 if node.key < order { 160 continue 161 } 162 163 switch node.key { 164 165 // 15. Comma operator 166 // 14. Assignment operators (right to left) 167 case symbols.Assign: 168 err = expAssign(tree, true) 169 case symbols.AssignUpdate: 170 err = expAssign(tree, false) 171 case symbols.AssignAndAdd: 172 err = expAssignAdd(tree) 173 case symbols.AssignAndSubtract: 174 err = expAssignAndOperate(tree, _assSub) 175 case symbols.AssignAndDivide: 176 err = expAssignAndOperate(tree, _assDiv) 177 case symbols.AssignAndMultiply: 178 err = expAssignAndOperate(tree, _assMulti) 179 case symbols.AssignAndMerge: 180 err = expAssignMerge(tree) 181 182 // 13. Conditional expression (ternary) 183 case symbols.NullCoalescing: 184 err = expNullCoalescing(tree) 185 case symbols.Elvis: 186 err = expElvis(tree) 187 188 // 12. Logical OR 189 case symbols.LogicalOr: 190 err = expLogicalOr(tree) 191 192 // 11. Logical AND 193 case symbols.LogicalAnd: 194 err = expLogicalAnd(tree) 195 196 // 10. Bitwise inclusive (normal) OR 197 // 09. Bitwise exclusive OR (XOR) 198 // 08. Bitwise AND 199 // 07. Comparisons: equal and not equal 200 case symbols.EqualTo: 201 err = expEqualTo(tree) 202 case symbols.NotEqualTo: 203 err = expNotEqualTo(tree) 204 case symbols.Like: 205 err = expLike(tree, true) 206 case symbols.NotLike: 207 err = expLike(tree, false) 208 case symbols.Regexp: 209 err = expRegexp(tree, true) 210 case symbols.NotRegexp: 211 err = expRegexp(tree, false) 212 213 // 06. Comparisons: less-than and greater-than 214 case symbols.GreaterThan: 215 err = expGtLt(tree, _gtF, _gtS) 216 case symbols.GreaterThanOrEqual: 217 err = expGtLt(tree, _gtEqF, _gtEqS) 218 case symbols.LessThan: 219 err = expGtLt(tree, _ltF, _ltS) 220 case symbols.LessThanOrEqual: 221 err = expGtLt(tree, _ltEqF, _ltEqS) 222 223 // 05. Bitwise shift left and right 224 // 04. Addition and subtraction 225 case symbols.Add: 226 err = expAdd(tree) 227 case symbols.Subtract: 228 err = expSubtract(tree) 229 case symbols.MergeInto: 230 err = expMergeInto(tree) 231 232 // 03. Multiplication, division, modulo 233 case symbols.Multiply: 234 err = expMultiply(tree) 235 case symbols.Divide: 236 err = expDivide(tree) 237 238 // 02. (most) unary operators, sizeof and type casts (right to left) 239 // 01. Function call, scope, array/member access 240 241 default: 242 err = raiseError(tree.expression, node, 0, fmt.Sprintf( 243 "no code written to handle symbol (%s)", 244 consts.IssueTrackerURL)) 245 } 246 247 if err != nil { 248 return err 249 } 250 251 tree.astPos = 0 252 } 253 254 return nil 255 } 256 ``` 257 258 ## See Also 259 260 * [`%[]` Create Array](../parser/create-array.md): 261 Quickly generate arrays 262 * [`%{}` Create Map](../parser/create-object.md): 263 Quickly generate objects and maps 264 * [`*=` Multiply By Operator](../parser/multiply-by.md): 265 Multiplies a variable by the right hand value (expression) 266 * [`*` Multiplication Operator](../parser/multiplication.md): 267 Multiplies one numeric value with another (expression) 268 * [`+=` Add With Operator](../parser/add-with.md): 269 Adds the right hand value to a variable (expression) 270 * [`+` Addition Operator](../parser/addition.md): 271 Adds two numeric values together (expression) 272 * [`-=` Subtract By Operator](../parser/subtract-by.md): 273 Subtracts a variable by the right hand value (expression) 274 * [`-` Subtraction Operator](../parser/subtraction.md): 275 Subtracts one numeric value from another (expression) 276 * [`/=` Divide By Operator](../parser/divide-by.md): 277 Divides a variable by the right hand value (expression) 278 * [`/` Division Operator](../parser/division.md): 279 Divides one numeric value from another (expression) 280 * [`?:` Elvis Operator](../parser/elvis.md): 281 Returns the right operand if the left operand is falsy (expression) 282 * [`??` Null Coalescing Operator](../parser/null-coalescing.md): 283 Returns the right operand if the left operand is empty / undefined (expression) 284 285 <hr/> 286 287 This document was generated from [builtins/core/expressions/expressions_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/expressions/expressions_doc.yaml).