mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
Support chzained comparisonc1 < 2 < 3 (#581)
This commit is contained in:
@@ -54,3 +54,7 @@ var Binary = map[string]Operator{
|
||||
"^": {100, Right},
|
||||
"??": {500, Left},
|
||||
}
|
||||
|
||||
func IsComparison(op string) bool {
|
||||
return op == "<" || op == ">" || op == ">=" || op == "<="
|
||||
}
|
||||
|
||||
@@ -164,6 +164,11 @@ func (p *parser) parseExpression(precedence int) Node {
|
||||
break
|
||||
}
|
||||
|
||||
if operator.IsComparison(opToken.Value) {
|
||||
nodeLeft = p.parseComparison(nodeLeft, opToken, op.Precedence)
|
||||
goto next
|
||||
}
|
||||
|
||||
var nodeRight Node
|
||||
if op.Associativity == operator.Left {
|
||||
nodeRight = p.parseExpression(op.Precedence + 1)
|
||||
@@ -685,3 +690,34 @@ func (p *parser) parsePostfixExpression(node Node) Node {
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *parser) parseComparison(left Node, token Token, precedence int) Node {
|
||||
var rootNode Node
|
||||
for {
|
||||
comparator := p.parseExpression(precedence + 1)
|
||||
cmpNode := &BinaryNode{
|
||||
Operator: token.Value,
|
||||
Left: left,
|
||||
Right: comparator,
|
||||
}
|
||||
cmpNode.SetLocation(token.Location)
|
||||
if rootNode == nil {
|
||||
rootNode = cmpNode
|
||||
} else {
|
||||
rootNode = &BinaryNode{
|
||||
Operator: "&&",
|
||||
Left: rootNode,
|
||||
Right: cmpNode,
|
||||
}
|
||||
rootNode.SetLocation(token.Location)
|
||||
}
|
||||
|
||||
left = comparator
|
||||
token = p.current
|
||||
if !(token.Is(Operator) && operator.IsComparison(token.Value) && p.err == nil) {
|
||||
break
|
||||
}
|
||||
p.next()
|
||||
}
|
||||
return rootNode
|
||||
}
|
||||
|
||||
@@ -531,6 +531,66 @@ world`},
|
||||
To: &IntegerNode{Value: 3},
|
||||
},
|
||||
},
|
||||
{
|
||||
`1 < 2 > 3`,
|
||||
&BinaryNode{
|
||||
Operator: "&&",
|
||||
Left: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 1},
|
||||
Right: &IntegerNode{Value: 2},
|
||||
},
|
||||
Right: &BinaryNode{
|
||||
Operator: ">",
|
||||
Left: &IntegerNode{Value: 2},
|
||||
Right: &IntegerNode{Value: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`1 < 2 < 3 < 4`,
|
||||
&BinaryNode{
|
||||
Operator: "&&",
|
||||
Left: &BinaryNode{
|
||||
Operator: "&&",
|
||||
Left: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 1},
|
||||
Right: &IntegerNode{Value: 2},
|
||||
},
|
||||
Right: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 2},
|
||||
Right: &IntegerNode{Value: 3},
|
||||
},
|
||||
},
|
||||
Right: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 3},
|
||||
Right: &IntegerNode{Value: 4},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`1 < 2 < 3 == true`,
|
||||
&BinaryNode{
|
||||
Operator: "==",
|
||||
Left: &BinaryNode{
|
||||
Operator: "&&",
|
||||
Left: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 1},
|
||||
Right: &IntegerNode{Value: 2},
|
||||
},
|
||||
Right: &BinaryNode{
|
||||
Operator: "<",
|
||||
Left: &IntegerNode{Value: 2},
|
||||
Right: &IntegerNode{Value: 3},
|
||||
},
|
||||
},
|
||||
Right: &BoolNode{Value: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.input, func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user