-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoperator.go
149 lines (132 loc) · 2.31 KB
/
operator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package esqb
/*
Represents the valid symbols for operators.
*/
type Operator int
const (
value Operator = iota
EQ
NEQ
GT
LT
GTE
LTE
and
or
negate
invert
bitwiseNot
)
const (
valuePrecedence = -iota
prefixPrecedence
comparatorPrecedence
logicalAndPrecedence
logicalOrPrecedence
)
func (it Operator) precedence() int {
switch it {
case value:
return valuePrecedence
case EQ:
fallthrough
case NEQ:
fallthrough
case GT:
fallthrough
case LT:
fallthrough
case GTE:
return comparatorPrecedence
case and:
return logicalAndPrecedence
case or:
return logicalOrPrecedence
case bitwiseNot:
fallthrough
case negate:
fallthrough
case invert:
return prefixPrecedence
}
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]Operator{
"==": EQ,
"!=": NEQ,
">": GT,
">=": GTE,
"<": LT,
"<=": LTE,
}
var logicalSymbols = map[string]Operator{
"&&": and,
"||": or,
}
var operatorSymbols = map[string]Operator{
"==": EQ,
"!=": NEQ,
">": GT,
">=": GTE,
"<": LT,
"<=": LTE,
"&&": and,
"||": or,
}
var prefixSymbols = map[string]Operator{
"-": negate,
"!": invert,
"~": bitwiseNot,
}
/*
Returns true if this Operator is contained by the given array of candidate symbols.
False otherwise.
*/
func (it Operator) IsModifierType(candidate []Operator) bool {
for _, symbolType := range candidate {
if it == 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
Operator 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 (it Operator) String() string {
switch it {
case value:
return "value"
case EQ:
return "="
case NEQ:
return "!="
case GT:
return ">"
case LT:
return "<"
case GTE:
return ">="
case LTE:
return "<="
case and:
return "&&"
case or:
return "||"
case negate:
return "-"
case invert:
return "!"
case bitwiseNot:
return "~"
}
return ""
}