@@ -58,6 +58,7 @@ var binaryOperators = map[string]operator{
5858 "%" : {60 , left },
5959 "**" : {100 , right },
6060 "^" : {100 , right },
61+ "??" : {500 , left },
6162}
6263
6364var builtins = map [string ]builtin {
@@ -113,9 +114,13 @@ func Parse(input string) (*Tree, error) {
113114}
114115
115116func (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 {}) {
116121 if p .err == nil { // show first error
117122 p .err = & file.Error {
118- Location : p . current .Location ,
123+ Location : token .Location ,
119124 Message : fmt .Sprintf (format , args ... ),
120125 }
121126 }
@@ -143,22 +148,28 @@ func (p *parser) expect(kind Kind, values ...string) {
143148func (p * parser ) parseExpression (precedence int ) Node {
144149 nodeLeft := p .parsePrimary ()
145150
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 {
148154 negate := false
149155 var notToken Token
150156
151- if token .Is (Operator , "not" ) {
157+ if opToken .Is (Operator , "not" ) {
152158 p .next ()
153159 notToken = p .current
154160 negate = true
155- token = p .current
161+ opToken = p .current
156162 }
157163
158- if op , ok := binaryOperators [token .Value ]; ok {
164+ if op , ok := binaryOperators [opToken .Value ]; ok {
159165 if op .precedence >= precedence {
160166 p .next ()
161167
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+
162173 var nodeRight Node
163174 if op .associativity == left {
164175 nodeRight = p .parseExpression (op .precedence + 1 )
@@ -167,11 +178,11 @@ func (p *parser) parseExpression(precedence int) Node {
167178 }
168179
169180 nodeLeft = & BinaryNode {
170- Operator : token .Value ,
181+ Operator : opToken .Value ,
171182 Left : nodeLeft ,
172183 Right : nodeRight ,
173184 }
174- nodeLeft .SetLocation (token .Location )
185+ nodeLeft .SetLocation (opToken .Location )
175186
176187 if negate {
177188 nodeLeft = & UnaryNode {
@@ -181,7 +192,8 @@ func (p *parser) parseExpression(precedence int) Node {
181192 nodeLeft .SetLocation (notToken .Location )
182193 }
183194
184- token = p .current
195+ lastOperator = opToken .Value
196+ opToken = p .current
185197 continue
186198 }
187199 }
0 commit comments