Skip to content

Commit d06fea9

Browse files
committed
Fix lexer to emit correct location with range operator
1 parent 9217dda commit d06fea9

File tree

4 files changed

+58
-27
lines changed

4 files changed

+58
-27
lines changed

cmd/exe/main.go

+29-21
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ import (
1919
)
2020

2121
var (
22-
bytecode bool
23-
debug bool
24-
run bool
25-
past bool
26-
dot bool
27-
repl bool
28-
opt bool
22+
bytecode bool
23+
debug bool
24+
run bool
25+
past bool
26+
dot bool
27+
repl bool
28+
opt bool
29+
typeCheck bool
2930
)
3031

3132
func init() {
@@ -36,6 +37,7 @@ func init() {
3637
flag.BoolVar(&dot, "dot", false, "dot format")
3738
flag.BoolVar(&repl, "repl", false, "start repl")
3839
flag.BoolVar(&opt, "opt", true, "do optimization")
40+
flag.BoolVar(&typeCheck, "type", true, "do a type check")
3941
}
4042

4143
func main() {
@@ -85,13 +87,15 @@ func printAst() {
8587
tree, err := parser.Parse(input())
8688
check(err)
8789

88-
_, err = checker.Check(tree, &conf.Config{
89-
AllowUndefinedVariables: true,
90-
})
91-
check(err)
90+
if typeCheck {
91+
_, err = checker.Check(tree, &conf.Config{
92+
AllowUndefinedVariables: true,
93+
})
94+
check(err)
9295

93-
if opt {
94-
optimizer.Optimize(&tree.Node)
96+
if opt {
97+
optimizer.Optimize(&tree.Node)
98+
}
9599
}
96100

97101
if !dot {
@@ -105,11 +109,13 @@ func printDisassemble() {
105109
tree, err := parser.Parse(input())
106110
check(err)
107111

108-
_, err = checker.Check(tree, nil)
109-
check(err)
112+
if typeCheck {
113+
_, err = checker.Check(tree, nil)
114+
check(err)
110115

111-
if opt {
112-
optimizer.Optimize(&tree.Node)
116+
if opt {
117+
optimizer.Optimize(&tree.Node)
118+
}
113119
}
114120

115121
program, err := compiler.Compile(tree, nil)
@@ -122,11 +128,13 @@ func runProgram() {
122128
tree, err := parser.Parse(input())
123129
check(err)
124130

125-
_, err = checker.Check(tree, nil)
126-
check(err)
131+
if typeCheck {
132+
_, err = checker.Check(tree, nil)
133+
check(err)
127134

128-
if opt {
129-
optimizer.Optimize(&tree.Node)
135+
if opt {
136+
optimizer.Optimize(&tree.Node)
137+
}
130138
}
131139

132140
program, err := compiler.Compile(tree, nil)

optimizer/optimizer_test.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/antonmedv/expr/internal/conf"
99
"github.com/antonmedv/expr/optimizer"
1010
"github.com/antonmedv/expr/parser"
11-
"github.com/sanity-io/litter"
1211
"github.com/stretchr/testify/assert"
1312
"github.com/stretchr/testify/require"
1413
)
@@ -24,7 +23,7 @@ func TestOptimize_constant_folding(t *testing.T) {
2423
Index: &ast.IntegerNode{Value: 0},
2524
}
2625

27-
assert.Equal(t, litter.Sdump(expected), litter.Sdump(tree.Node))
26+
assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node))
2827
}
2928

3029
func TestOptimize_in_array(t *testing.T) {
@@ -44,7 +43,7 @@ func TestOptimize_in_array(t *testing.T) {
4443
Right: &ast.ConstantNode{Value: optimizer.Map{1: {}, 2: {}, 3: {}}},
4544
}
4645

47-
assert.Equal(t, litter.Sdump(expected), litter.Sdump(tree.Node))
46+
assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node))
4847
}
4948

5049
func TestOptimize_in_range(t *testing.T) {
@@ -74,7 +73,7 @@ func TestOptimize_in_range(t *testing.T) {
7473
},
7574
}
7675

77-
assert.Equal(t, litter.Sdump(expected), litter.Sdump(tree.Node))
76+
assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node))
7877
}
7978

8079
func TestOptimize_const_range(t *testing.T) {
@@ -87,5 +86,5 @@ func TestOptimize_const_range(t *testing.T) {
8786
Value: []int{-1, 0, 1},
8887
}
8988

90-
assert.Equal(t, litter.Sdump(expected), litter.Sdump(tree.Node))
89+
assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node))
9190
}

parser/lexer/lexer_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lexer_test
33
import (
44
"fmt"
55
"github.com/stretchr/testify/assert"
6+
"github.com/stretchr/testify/require"
67
"strings"
78
"testing"
89

@@ -117,6 +118,21 @@ func TestLex(t *testing.T) {
117118
}
118119
}
119120

121+
func TestLex_location(t *testing.T) {
122+
source := file.NewSource("1..2 3..4")
123+
tokens, err := Lex(source)
124+
require.NoError(t, err)
125+
require.Equal(t, []Token{
126+
{Location: file.Location{Line: 1, Column: 0}, Kind: Number, Value: "1"},
127+
{Location: file.Location{Line: 1, Column: 1}, Kind: Operator, Value: ".."},
128+
{Location: file.Location{Line: 1, Column: 3}, Kind: Number, Value: "2"},
129+
{Location: file.Location{Line: 1, Column: 5}, Kind: Number, Value: "3"},
130+
{Location: file.Location{Line: 1, Column: 6}, Kind: Operator, Value: ".."},
131+
{Location: file.Location{Line: 1, Column: 8}, Kind: Number, Value: "4"},
132+
{Location: file.Location{Line: 1, Column: 8}, Kind: EOF, Value: ""},
133+
}, tokens)
134+
}
135+
120136
const errorTests = `
121137
"\xQA"
122138
invalid char escape (1:5)

parser/lexer/state.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,18 @@ func (l *lexer) scanNumber() bool {
6767
}
6868
}
6969
l.acceptRun(digits)
70+
end := l.end
71+
loc := l.loc
72+
prev := l.prev
7073
if l.accept(".") {
7174
// Lookup for .. operator: if after dot there is another dot (1..2), it maybe a range operator.
7275
if l.peek() == '.' {
73-
l.backup()
76+
// We can't backup() here, as it would require two backups,
77+
// and backup() func supports only one for now. So, save and
78+
// restore it here.
79+
l.end = end
80+
l.loc = loc
81+
l.prev = prev
7482
return true
7583
}
7684
l.acceptRun(digits)

0 commit comments

Comments
 (0)