OperatorSymbol.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package govaluate
  2. /*
  3. Represents the valid symbols for operators.
  4. */
  5. type OperatorSymbol int
  6. const (
  7. VALUE OperatorSymbol = iota
  8. LITERAL
  9. NOOP
  10. EQ
  11. NEQ
  12. GT
  13. LT
  14. GTE
  15. LTE
  16. REQ
  17. NREQ
  18. IN
  19. AND
  20. OR
  21. PLUS
  22. MINUS
  23. BITWISE_AND
  24. BITWISE_OR
  25. BITWISE_XOR
  26. BITWISE_LSHIFT
  27. BITWISE_RSHIFT
  28. MULTIPLY
  29. DIVIDE
  30. MODULUS
  31. EXPONENT
  32. NEGATE
  33. INVERT
  34. BITWISE_NOT
  35. TERNARY_TRUE
  36. TERNARY_FALSE
  37. COALESCE
  38. FUNCTIONAL
  39. SEPARATE
  40. )
  41. type operatorPrecedence int
  42. const (
  43. noopPrecedence operatorPrecedence = iota
  44. valuePrecedence
  45. functionalPrecedence
  46. prefixPrecedence
  47. exponentialPrecedence
  48. additivePrecedence
  49. bitwisePrecedence
  50. bitwiseShiftPrecedence
  51. multiplicativePrecedence
  52. comparatorPrecedence
  53. ternaryPrecedence
  54. logicalAndPrecedence
  55. logicalOrPrecedence
  56. separatePrecedence
  57. )
  58. func findOperatorPrecedenceForSymbol(symbol OperatorSymbol) operatorPrecedence {
  59. switch symbol {
  60. case NOOP:
  61. return noopPrecedence
  62. case VALUE:
  63. return valuePrecedence
  64. case EQ:
  65. fallthrough
  66. case NEQ:
  67. fallthrough
  68. case GT:
  69. fallthrough
  70. case LT:
  71. fallthrough
  72. case GTE:
  73. fallthrough
  74. case LTE:
  75. fallthrough
  76. case REQ:
  77. fallthrough
  78. case NREQ:
  79. fallthrough
  80. case IN:
  81. return comparatorPrecedence
  82. case AND:
  83. return logicalAndPrecedence
  84. case OR:
  85. return logicalOrPrecedence
  86. case BITWISE_AND:
  87. fallthrough
  88. case BITWISE_OR:
  89. fallthrough
  90. case BITWISE_XOR:
  91. return bitwisePrecedence
  92. case BITWISE_LSHIFT:
  93. fallthrough
  94. case BITWISE_RSHIFT:
  95. return bitwiseShiftPrecedence
  96. case PLUS:
  97. fallthrough
  98. case MINUS:
  99. return additivePrecedence
  100. case MULTIPLY:
  101. fallthrough
  102. case DIVIDE:
  103. fallthrough
  104. case MODULUS:
  105. return multiplicativePrecedence
  106. case EXPONENT:
  107. return exponentialPrecedence
  108. case BITWISE_NOT:
  109. fallthrough
  110. case NEGATE:
  111. fallthrough
  112. case INVERT:
  113. return prefixPrecedence
  114. case COALESCE:
  115. fallthrough
  116. case TERNARY_TRUE:
  117. fallthrough
  118. case TERNARY_FALSE:
  119. return ternaryPrecedence
  120. case FUNCTIONAL:
  121. return functionalPrecedence
  122. case SEPARATE:
  123. return separatePrecedence
  124. }
  125. return valuePrecedence
  126. }
  127. /*
  128. Map of all valid comparators, and their string equivalents.
  129. Used during parsing of expressions to determine if a symbol is, in fact, a comparator.
  130. Also used during evaluation to determine exactly which comparator is being used.
  131. */
  132. var comparatorSymbols = map[string]OperatorSymbol{
  133. "==": EQ,
  134. "!=": NEQ,
  135. ">": GT,
  136. ">=": GTE,
  137. "<": LT,
  138. "<=": LTE,
  139. "=~": REQ,
  140. "!~": NREQ,
  141. "in": IN,
  142. }
  143. var logicalSymbols = map[string]OperatorSymbol{
  144. "&&": AND,
  145. "||": OR,
  146. }
  147. var bitwiseSymbols = map[string]OperatorSymbol{
  148. "^": BITWISE_XOR,
  149. "&": BITWISE_AND,
  150. "|": BITWISE_OR,
  151. }
  152. var bitwiseShiftSymbols = map[string]OperatorSymbol{
  153. ">>": BITWISE_RSHIFT,
  154. "<<": BITWISE_LSHIFT,
  155. }
  156. var additiveSymbols = map[string]OperatorSymbol{
  157. "+": PLUS,
  158. "-": MINUS,
  159. }
  160. var multiplicativeSymbols = map[string]OperatorSymbol{
  161. "*": MULTIPLY,
  162. "/": DIVIDE,
  163. "%": MODULUS,
  164. }
  165. var exponentialSymbolsS = map[string]OperatorSymbol{
  166. "**": EXPONENT,
  167. }
  168. var prefixSymbols = map[string]OperatorSymbol{
  169. "-": NEGATE,
  170. "!": INVERT,
  171. "~": BITWISE_NOT,
  172. }
  173. var ternarySymbols = map[string]OperatorSymbol{
  174. "?": TERNARY_TRUE,
  175. ":": TERNARY_FALSE,
  176. "??": COALESCE,
  177. }
  178. // this is defined separately from additiveSymbols et al because it's needed for parsing, not stage planning.
  179. var modifierSymbols = map[string]OperatorSymbol{
  180. "+": PLUS,
  181. "-": MINUS,
  182. "*": MULTIPLY,
  183. "/": DIVIDE,
  184. "%": MODULUS,
  185. "**": EXPONENT,
  186. "&": BITWISE_AND,
  187. "|": BITWISE_OR,
  188. "^": BITWISE_XOR,
  189. ">>": BITWISE_RSHIFT,
  190. "<<": BITWISE_LSHIFT,
  191. }
  192. var separatorSymbols = map[string]OperatorSymbol{
  193. ",": SEPARATE,
  194. }
  195. /*
  196. Returns true if this operator is contained by the given array of candidate symbols.
  197. False otherwise.
  198. */
  199. func (this OperatorSymbol) IsModifierType(candidate []OperatorSymbol) bool {
  200. for _, symbolType := range candidate {
  201. if this == symbolType {
  202. return true
  203. }
  204. }
  205. return false
  206. }
  207. /*
  208. Generally used when formatting type check errors.
  209. We could store the stringified symbol somewhere else and not require a duplicated codeblock to translate
  210. OperatorSymbol to string, but that would require more memory, and another field somewhere.
  211. Adding operators is rare enough that we just stringify it here instead.
  212. */
  213. func (this OperatorSymbol) String() string {
  214. switch this {
  215. case NOOP:
  216. return "NOOP"
  217. case VALUE:
  218. return "VALUE"
  219. case EQ:
  220. return "="
  221. case NEQ:
  222. return "!="
  223. case GT:
  224. return ">"
  225. case LT:
  226. return "<"
  227. case GTE:
  228. return ">="
  229. case LTE:
  230. return "<="
  231. case REQ:
  232. return "=~"
  233. case NREQ:
  234. return "!~"
  235. case AND:
  236. return "&&"
  237. case OR:
  238. return "||"
  239. case IN:
  240. return "in"
  241. case BITWISE_AND:
  242. return "&"
  243. case BITWISE_OR:
  244. return "|"
  245. case BITWISE_XOR:
  246. return "^"
  247. case BITWISE_LSHIFT:
  248. return "<<"
  249. case BITWISE_RSHIFT:
  250. return ">>"
  251. case PLUS:
  252. return "+"
  253. case MINUS:
  254. return "-"
  255. case MULTIPLY:
  256. return "*"
  257. case DIVIDE:
  258. return "/"
  259. case MODULUS:
  260. return "%"
  261. case EXPONENT:
  262. return "**"
  263. case NEGATE:
  264. return "-"
  265. case INVERT:
  266. return "!"
  267. case BITWISE_NOT:
  268. return "~"
  269. case TERNARY_TRUE:
  270. return "?"
  271. case TERNARY_FALSE:
  272. return ":"
  273. case COALESCE:
  274. return "??"
  275. }
  276. return ""
  277. }