Skip to content

Commit 1366bde

Browse files
committed
Enable comparison feature like python
1 parent 6bbe56c commit 1366bde

File tree

1 file changed

+45
-18
lines changed

1 file changed

+45
-18
lines changed

parser/parser.go

+45-18
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,26 @@ func (p *parser) expect(kind Kind, values ...string) {
127127
}
128128

129129
// parse functions
130-
131130
func (p *parser) parseExpression(precedence int) Node {
132131
if precedence == 0 && p.current.Is(Operator, "let") {
133132
return p.parseVariableDeclaration()
134133
}
135134

136135
nodeLeft := p.parsePrimary()
136+
137137
prevOperator := ""
138-
for opToken := p.current; opToken.Is(Operator) && p.err == nil; opToken = p.current {
138+
opToken := p.current
139+
for opToken.Is(Operator) && p.err == nil {
139140
negate := opToken.Is(Operator, "not")
140-
var op operator.Operator
141-
var ok bool
141+
var notToken Token
142+
143+
// Handle "not *" operator, like "not in" or "not contains".
142144
if negate {
143145
currentPos := p.pos
144146
p.next()
145147
if operator.AllowedNegateSuffix(p.current.Value) {
146-
if op, ok = operator.Binary[p.current.Value]; ok && op.Precedence >= precedence {
148+
if op, ok := operator.Binary[p.current.Value]; ok && op.Precedence >= precedence {
149+
notToken = p.current
147150
opToken = p.current
148151
} else {
149152
p.pos = currentPos
@@ -154,39 +157,63 @@ func (p *parser) parseExpression(precedence int) Node {
154157
p.error("unexpected token %v", p.current)
155158
break
156159
}
157-
} else if op, ok = operator.Binary[opToken.Value]; !ok || op.Precedence < precedence {
158-
break
159160
}
160-
p.next()
161-
if opToken.Value == "|" {
162-
identToken := p.current
163-
p.expect(Identifier)
164-
nodeLeft = p.parseCall(identToken, []Node{nodeLeft}, true)
165-
} else if prevOperator == "??" && opToken.Value != "??" && !opToken.Is(Bracket, "(") {
166-
p.errorAt(opToken, "Operator (%v) and coalesce expressions (??) cannot be mixed. Wrap either by parentheses.", opToken.Value)
167-
break
168-
} else if op.Precedence == 20 {
169-
nodeLeft = p.parseComparison(nodeLeft, opToken, op.Precedence+1, negate)
170-
} else {
161+
162+
if op, ok := operator.Binary[opToken.Value]; ok && op.Precedence >= precedence {
163+
p.next()
164+
165+
if opToken.Value == "|" {
166+
identToken := p.current
167+
p.expect(Identifier)
168+
nodeLeft = p.parseCall(identToken, []Node{nodeLeft}, true)
169+
goto next
170+
}
171+
172+
if prevOperator == "??" && opToken.Value != "??" && !opToken.Is(Bracket, "(") {
173+
p.errorAt(opToken, "Operator (%v) and coalesce expressions (??) cannot be mixed. Wrap either by parentheses.", opToken.Value)
174+
break
175+
}
176+
177+
if op.Precedence == 20 {
178+
nodeLeft = p.parseComparison(nodeLeft, opToken, op.Precedence+1, negate)
179+
goto next
180+
}
181+
171182
var nodeRight Node
172183
if op.Associativity == operator.Left {
173184
nodeRight = p.parseExpression(op.Precedence + 1)
174185
} else {
175186
nodeRight = p.parseExpression(op.Precedence)
176187
}
188+
177189
nodeLeft = &BinaryNode{
178190
Operator: opToken.Value,
179191
Left: nodeLeft,
180192
Right: nodeRight,
181193
}
182194
nodeLeft.SetLocation(opToken.Location)
195+
196+
if negate {
197+
nodeLeft = &UnaryNode{
198+
Operator: "not",
199+
Node: nodeLeft,
200+
}
201+
nodeLeft.SetLocation(notToken.Location)
202+
}
203+
204+
goto next
183205
}
206+
break
207+
208+
next:
184209
prevOperator = opToken.Value
210+
opToken = p.current
185211
}
186212

187213
if precedence == 0 {
188214
nodeLeft = p.parseConditional(nodeLeft)
189215
}
216+
190217
return nodeLeft
191218
}
192219

0 commit comments

Comments
 (0)