github.com/richardwilkes/toolbox@v1.121.0/eval/operator.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package eval 11 12 import ( 13 "unicode" 14 "unicode/utf8" 15 ) 16 17 // OpFunc provides a signature for an Operator's Evaluate function. 18 type OpFunc func(left, right any) (any, error) 19 20 // UnaryOpFunc provides a signature for an Operator's EvaluateUnary function. 21 type UnaryOpFunc func(arg any) (any, error) 22 23 // Operator provides an operator implementation for the Evaluator. 24 type Operator struct { 25 Evaluate OpFunc 26 EvaluateUnary UnaryOpFunc 27 Symbol string 28 Precedence int 29 } 30 31 func (o *Operator) match(expression string, start, maximum int) bool { 32 if maximum-start < len(o.Symbol) { 33 return false 34 } 35 matches := o.Symbol == expression[start:start+len(o.Symbol)] 36 // Hack to allow negative exponents on floating point numbers (i.e. 1.2e-2) 37 if matches && len(o.Symbol) == 1 && o.Symbol == "-" && start > 1 && expression[start-1:start] == "e" { 38 ch, _ := utf8.DecodeRuneInString(expression[start-2 : start-1]) 39 if unicode.IsDigit(ch) { 40 return false 41 } 42 } 43 return matches 44 } 45 46 // OpenParen ( 47 func OpenParen() *Operator { 48 return &Operator{Symbol: "("} 49 } 50 51 // CloseParen ) 52 func CloseParen() *Operator { 53 return &Operator{Symbol: ")"} 54 } 55 56 // Not ! 57 func Not(f UnaryOpFunc) *Operator { 58 return &Operator{ 59 Symbol: "!", 60 EvaluateUnary: f, 61 } 62 } 63 64 // LogicalOr || 65 func LogicalOr(f OpFunc) *Operator { 66 return &Operator{ 67 Symbol: "||", 68 Precedence: 10, 69 Evaluate: f, 70 } 71 } 72 73 // LogicalAnd && 74 func LogicalAnd(f OpFunc) *Operator { 75 return &Operator{ 76 Symbol: "&&", 77 Precedence: 20, 78 Evaluate: f, 79 } 80 } 81 82 // Equal == 83 func Equal(f OpFunc) *Operator { 84 return &Operator{ 85 Symbol: "==", 86 Precedence: 30, 87 Evaluate: f, 88 } 89 } 90 91 // NotEqual != 92 func NotEqual(f OpFunc) *Operator { 93 return &Operator{ 94 Symbol: "!=", 95 Precedence: 30, 96 Evaluate: f, 97 } 98 } 99 100 // GreaterThan > 101 func GreaterThan(f OpFunc) *Operator { 102 return &Operator{ 103 Symbol: ">", 104 Precedence: 40, 105 Evaluate: f, 106 } 107 } 108 109 // GreaterThanOrEqual >= 110 func GreaterThanOrEqual(f OpFunc) *Operator { 111 return &Operator{ 112 Symbol: ">=", 113 Precedence: 40, 114 Evaluate: f, 115 } 116 } 117 118 // LessThan < 119 func LessThan(f OpFunc) *Operator { 120 return &Operator{ 121 Symbol: "<", 122 Precedence: 40, 123 Evaluate: f, 124 } 125 } 126 127 // LessThanOrEqual <= 128 func LessThanOrEqual(f OpFunc) *Operator { 129 return &Operator{ 130 Symbol: "<=", 131 Precedence: 40, 132 Evaluate: f, 133 } 134 } 135 136 // Add + 137 func Add(f OpFunc, unary UnaryOpFunc) *Operator { 138 return &Operator{ 139 Symbol: "+", 140 Precedence: 50, 141 Evaluate: f, 142 EvaluateUnary: unary, 143 } 144 } 145 146 // Subtract - 147 func Subtract(f OpFunc, unary UnaryOpFunc) *Operator { 148 return &Operator{ 149 Symbol: "-", 150 Precedence: 50, 151 Evaluate: f, 152 EvaluateUnary: unary, 153 } 154 } 155 156 // Multiply * 157 func Multiply(f OpFunc) *Operator { 158 return &Operator{ 159 Symbol: "*", 160 Precedence: 60, 161 Evaluate: f, 162 } 163 } 164 165 // Divide / 166 func Divide(f OpFunc) *Operator { 167 return &Operator{ 168 Symbol: "/", 169 Precedence: 60, 170 Evaluate: f, 171 } 172 } 173 174 // Modulo % 175 func Modulo(f OpFunc) *Operator { 176 return &Operator{ 177 Symbol: "%", 178 Precedence: 60, 179 Evaluate: f, 180 } 181 } 182 183 // Power ^ 184 func Power(f OpFunc) *Operator { 185 return &Operator{ 186 Symbol: "^", 187 Precedence: 70, 188 Evaluate: f, 189 } 190 }