123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- package govaluate
- /*
- Represents the valid symbols for operators.
- */
- type OperatorSymbol int
- const (
- VALUE OperatorSymbol = iota
- LITERAL
- NOOP
- EQ
- NEQ
- GT
- LT
- GTE
- LTE
- REQ
- NREQ
- IN
- AND
- OR
- PLUS
- MINUS
- BITWISE_AND
- BITWISE_OR
- BITWISE_XOR
- BITWISE_LSHIFT
- BITWISE_RSHIFT
- MULTIPLY
- DIVIDE
- MODULUS
- EXPONENT
- NEGATE
- INVERT
- BITWISE_NOT
- TERNARY_TRUE
- TERNARY_FALSE
- COALESCE
- FUNCTIONAL
- SEPARATE
- )
- type operatorPrecedence int
- const (
- noopPrecedence operatorPrecedence = iota
- valuePrecedence
- functionalPrecedence
- prefixPrecedence
- exponentialPrecedence
- additivePrecedence
- bitwisePrecedence
- bitwiseShiftPrecedence
- multiplicativePrecedence
- comparatorPrecedence
- ternaryPrecedence
- logicalAndPrecedence
- logicalOrPrecedence
- separatePrecedence
- )
- func findOperatorPrecedenceForSymbol(symbol OperatorSymbol) operatorPrecedence {
- switch symbol {
- case NOOP:
- return noopPrecedence
- case VALUE:
- return valuePrecedence
- case EQ:
- fallthrough
- case NEQ:
- fallthrough
- case GT:
- fallthrough
- case LT:
- fallthrough
- case GTE:
- fallthrough
- case LTE:
- fallthrough
- case REQ:
- fallthrough
- case NREQ:
- fallthrough
- case IN:
- return comparatorPrecedence
- case AND:
- return logicalAndPrecedence
- case OR:
- return logicalOrPrecedence
- case BITWISE_AND:
- fallthrough
- case BITWISE_OR:
- fallthrough
- case BITWISE_XOR:
- return bitwisePrecedence
- case BITWISE_LSHIFT:
- fallthrough
- case BITWISE_RSHIFT:
- return bitwiseShiftPrecedence
- case PLUS:
- fallthrough
- case MINUS:
- return additivePrecedence
- case MULTIPLY:
- fallthrough
- case DIVIDE:
- fallthrough
- case MODULUS:
- return multiplicativePrecedence
- case EXPONENT:
- return exponentialPrecedence
- case BITWISE_NOT:
- fallthrough
- case NEGATE:
- fallthrough
- case INVERT:
- return prefixPrecedence
- case COALESCE:
- fallthrough
- case TERNARY_TRUE:
- fallthrough
- case TERNARY_FALSE:
- return ternaryPrecedence
- case FUNCTIONAL:
- return functionalPrecedence
- case SEPARATE:
- return separatePrecedence
- }
- return valuePrecedence
- }
- /*
- Map of all valid comparators, and their string equivalents.
- Used during parsing of expressions to determine if a symbol is, in fact, a comparator.
- Also used during evaluation to determine exactly which comparator is being used.
- */
- var comparatorSymbols = map[string]OperatorSymbol{
- "==": EQ,
- "!=": NEQ,
- ">": GT,
- ">=": GTE,
- "<": LT,
- "<=": LTE,
- "=~": REQ,
- "!~": NREQ,
- "in": IN,
- }
- var logicalSymbols = map[string]OperatorSymbol{
- "&&": AND,
- "||": OR,
- }
- var bitwiseSymbols = map[string]OperatorSymbol{
- "^": BITWISE_XOR,
- "&": BITWISE_AND,
- "|": BITWISE_OR,
- }
- var bitwiseShiftSymbols = map[string]OperatorSymbol{
- ">>": BITWISE_RSHIFT,
- "<<": BITWISE_LSHIFT,
- }
- var additiveSymbols = map[string]OperatorSymbol{
- "+": PLUS,
- "-": MINUS,
- }
- var multiplicativeSymbols = map[string]OperatorSymbol{
- "*": MULTIPLY,
- "/": DIVIDE,
- "%": MODULUS,
- }
- var exponentialSymbolsS = map[string]OperatorSymbol{
- "**": EXPONENT,
- }
- var prefixSymbols = map[string]OperatorSymbol{
- "-": NEGATE,
- "!": INVERT,
- "~": BITWISE_NOT,
- }
- var ternarySymbols = map[string]OperatorSymbol{
- "?": TERNARY_TRUE,
- ":": TERNARY_FALSE,
- "??": COALESCE,
- }
- // this is defined separately from additiveSymbols et al because it's needed for parsing, not stage planning.
- var modifierSymbols = map[string]OperatorSymbol{
- "+": PLUS,
- "-": MINUS,
- "*": MULTIPLY,
- "/": DIVIDE,
- "%": MODULUS,
- "**": EXPONENT,
- "&": BITWISE_AND,
- "|": BITWISE_OR,
- "^": BITWISE_XOR,
- ">>": BITWISE_RSHIFT,
- "<<": BITWISE_LSHIFT,
- }
- var separatorSymbols = map[string]OperatorSymbol{
- ",": SEPARATE,
- }
- /*
- Returns true if this operator is contained by the given array of candidate symbols.
- False otherwise.
- */
- func (this OperatorSymbol) IsModifierType(candidate []OperatorSymbol) bool {
- for _, symbolType := range candidate {
- if this == symbolType {
- return true
- }
- }
- return false
- }
- /*
- Generally used when formatting type check errors.
- We could store the stringified symbol somewhere else and not require a duplicated codeblock to translate
- OperatorSymbol to string, but that would require more memory, and another field somewhere.
- Adding operators is rare enough that we just stringify it here instead.
- */
- func (this OperatorSymbol) String() string {
- switch this {
- case NOOP:
- return "NOOP"
- case VALUE:
- return "VALUE"
- case EQ:
- return "="
- case NEQ:
- return "!="
- case GT:
- return ">"
- case LT:
- return "<"
- case GTE:
- return ">="
- case LTE:
- return "<="
- case REQ:
- return "=~"
- case NREQ:
- return "!~"
- case AND:
- return "&&"
- case OR:
- return "||"
- case IN:
- return "in"
- case BITWISE_AND:
- return "&"
- case BITWISE_OR:
- return "|"
- case BITWISE_XOR:
- return "^"
- case BITWISE_LSHIFT:
- return "<<"
- case BITWISE_RSHIFT:
- return ">>"
- case PLUS:
- return "+"
- case MINUS:
- return "-"
- case MULTIPLY:
- return "*"
- case DIVIDE:
- return "/"
- case MODULUS:
- return "%"
- case EXPONENT:
- return "**"
- case NEGATE:
- return "-"
- case INVERT:
- return "!"
- case BITWISE_NOT:
- return "~"
- case TERNARY_TRUE:
- return "?"
- case TERNARY_FALSE:
- return ":"
- case COALESCE:
- return "??"
- }
- return ""
- }
|