Skip to content

Commit

Permalink
fix: logic operator parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
douyixuan committed Nov 27, 2024
1 parent 2eb378c commit 28b6ce2
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
17 changes: 17 additions & 0 deletions compiler/lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,20 @@ func TestLexerPragma(t *testing.T) {

assert.Equal(t, expected, r)
}

func TestCondition(t *testing.T) {
r := Lex(`a > b && b > c`)

expected := []Item{
{Type: IDENTIFIER, Val: "a", Line: 1},
{Type: OPERATOR, Val: ">", Line: 1},
{Type: IDENTIFIER, Val: "b", Line: 1},
{Type: OPERATOR, Val: "&&", Line: 1},
{Type: IDENTIFIER, Val: "b", Line: 1},
{Type: OPERATOR, Val: ">", Line: 1},
{Type: IDENTIFIER, Val: "c", Line: 1},
{Type: EOL},
{Type: EOF},
}
assert.Equal(t, expected, r)
}
8 changes: 8 additions & 0 deletions compiler/parser/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const (

var opsCharToOp map[string]Operator
var arithOperators map[Operator]struct{}
var cmpOperators map[Operator]struct{}

func init() {
opsCharToOp = make(map[string]Operator)
Expand All @@ -136,6 +137,13 @@ func init() {
} {
arithOperators[op] = struct{}{}
}

cmpOperators = make(map[Operator]struct{})
for _, op := range []Operator{
OP_EQ, OP_GT, OP_GTEQ, OP_LT, OP_LTEQ,
} {
cmpOperators[op] = struct{}{}
}
}

func (on OperatorNode) String() string {
Expand Down
17 changes: 17 additions & 0 deletions compiler/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ func (p *parser) parseOperation(input Node, withArithAhead bool) Node {
// Handle "Operations" both arith and comparision
operator := opsCharToOp[next.Val]
_, isArithOp := arithOperators[operator]
_, isCmpOp := cmpOperators[operator]

if !withArithAhead && isArithOp {
return input
Expand All @@ -764,11 +765,27 @@ func (p *parser) parseOperation(input Node, withArithAhead bool) Node {
Operator: operator,
Left: input,
}
if operator == OP_LOGICAL_AND || operator == OP_LOGICAL_OR {
body, _ := p.parseUntilEither(
[]lexer.Item{
{Type: lexer.OPERATOR, Val: "{"},
{Type: lexer.EOL},
{Type: lexer.EOF},
},
)
return &OperatorNode{
Operator: operator,
Left: input,
Right: body[0],
}
}

if isArithOp {
res.Right = p.parseOneWithOptions(false, false, false)
// Sort infix operations if necessary (eg: apply OP_MUL before OP_ADD)
res = sortInfix(res)
} else if isCmpOp {
res.Right = p.parseOneWithOptions(false, false, false)
} else {
res.Right = p.parseOneWithOptions(true, true, true)
}
Expand Down
38 changes: 38 additions & 0 deletions compiler/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,41 @@ func TestFunction(t *testing.T) {

assert.Equal(t, expected, Parse(input, &option.Options{Debug: false}))
}

func TestCondition(t *testing.T) {
input := []lexer.Item{
{Type: lexer.IDENTIFIER, Val: "a", Line: 1},
{Type: lexer.OPERATOR, Val: ">", Line: 1},
{Type: lexer.IDENTIFIER, Val: "b", Line: 1},
{Type: lexer.OPERATOR, Val: "&&", Line: 1},
{Type: lexer.IDENTIFIER, Val: "b", Line: 1},
{Type: lexer.OPERATOR, Val: ">", Line: 1},
{Type: lexer.IDENTIFIER, Val: "c", Line: 1},
{Type: lexer.EOL},
{Type: lexer.EOF},
}

/*
a > b && b > c
*/

expected := &FileNode{
Instructions: []Node{
&OperatorNode{
Operator: "&&",
Left: &OperatorNode{
Operator: ">",
Left: &NameNode{Name: "a"},
Right: &NameNode{Name: "b"},
},
Right: &OperatorNode{
Operator: ">",
Left: &NameNode{Name: "b"},
Right: &NameNode{Name: "c"},
},
},
},
}

assert.Equal(t, expected, Parse(input, &option.Options{Debug: false}))
}

0 comments on commit 28b6ce2

Please sign in to comment.