@@ -58,6 +58,7 @@ var binaryOperators = map[string]operator{
58
58
"%" : {60 , left },
59
59
"**" : {100 , right },
60
60
"^" : {100 , right },
61
+ "??" : {500 , left },
61
62
}
62
63
63
64
var builtins = map [string ]builtin {
@@ -113,9 +114,13 @@ func Parse(input string) (*Tree, error) {
113
114
}
114
115
115
116
func (p * parser ) error (format string , args ... interface {}) {
117
+ p .errorAt (p .current , format , args ... )
118
+ }
119
+
120
+ func (p * parser ) errorAt (token Token , format string , args ... interface {}) {
116
121
if p .err == nil { // show first error
117
122
p .err = & file.Error {
118
- Location : p . current .Location ,
123
+ Location : token .Location ,
119
124
Message : fmt .Sprintf (format , args ... ),
120
125
}
121
126
}
@@ -143,22 +148,28 @@ func (p *parser) expect(kind Kind, values ...string) {
143
148
func (p * parser ) parseExpression (precedence int ) Node {
144
149
nodeLeft := p .parsePrimary ()
145
150
146
- token := p .current
147
- for token .Is (Operator ) && p .err == nil {
151
+ lastOperator := ""
152
+ opToken := p .current
153
+ for opToken .Is (Operator ) && p .err == nil {
148
154
negate := false
149
155
var notToken Token
150
156
151
- if token .Is (Operator , "not" ) {
157
+ if opToken .Is (Operator , "not" ) {
152
158
p .next ()
153
159
notToken = p .current
154
160
negate = true
155
- token = p .current
161
+ opToken = p .current
156
162
}
157
163
158
- if op , ok := binaryOperators [token .Value ]; ok {
164
+ if op , ok := binaryOperators [opToken .Value ]; ok {
159
165
if op .precedence >= precedence {
160
166
p .next ()
161
167
168
+ if lastOperator == "??" && opToken .Value != "??" && ! opToken .Is (Bracket , "(" ) {
169
+ p .errorAt (opToken , "Operator (%v) and coalesce expressions (??) cannot be mixed. Wrap either by parentheses." , opToken .Value )
170
+ break
171
+ }
172
+
162
173
var nodeRight Node
163
174
if op .associativity == left {
164
175
nodeRight = p .parseExpression (op .precedence + 1 )
@@ -167,11 +178,11 @@ func (p *parser) parseExpression(precedence int) Node {
167
178
}
168
179
169
180
nodeLeft = & BinaryNode {
170
- Operator : token .Value ,
181
+ Operator : opToken .Value ,
171
182
Left : nodeLeft ,
172
183
Right : nodeRight ,
173
184
}
174
- nodeLeft .SetLocation (token .Location )
185
+ nodeLeft .SetLocation (opToken .Location )
175
186
176
187
if negate {
177
188
nodeLeft = & UnaryNode {
@@ -181,7 +192,8 @@ func (p *parser) parseExpression(precedence int) Node {
181
192
nodeLeft .SetLocation (notToken .Location )
182
193
}
183
194
184
- token = p .current
195
+ lastOperator = opToken .Value
196
+ opToken = p .current
185
197
continue
186
198
}
187
199
}
0 commit comments