Skip to content

Commit f0783cd

Browse files
committed
Refactor to use new parser
1 parent 95fa24f commit f0783cd

File tree

12 files changed

+97
-57
lines changed

12 files changed

+97
-57
lines changed

ast/node.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@ import (
1010
// Node represents items of abstract syntax tree.
1111
type Node interface {
1212
Location() file.Location
13+
SetLocation(file.Location)
1314
Type() reflect.Type
1415
SetType(reflect.Type)
1516
}
1617

1718
type Base struct {
18-
Loc file.Location
19+
loc file.Location
1920
nodeType reflect.Type
2021
}
2122

2223
func (n *Base) Location() file.Location {
23-
return n.Loc
24+
return n.loc
25+
}
26+
27+
func (n *Base) SetLocation(loc file.Location) {
28+
n.loc = loc
2429
}
2530

2631
func (n *Base) Type() reflect.Type {
@@ -32,7 +37,7 @@ func (n *Base) SetType(t reflect.Type) {
3237
}
3338

3439
func Loc(l file.Location) Base {
35-
return Base{Loc: l}
40+
return Base{loc: l}
3641
}
3742

3843
type NilNode struct {

checker/checker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func (v *visitor) visit(node ast.Node) reflect.Type {
115115

116116
func (v *visitor) error(node ast.Node, format string, args ...interface{}) file.Error {
117117
return file.Error{
118-
Location: node.GetLocation(),
118+
Location: node.Location(),
119119
Message: fmt.Sprintf(format, args...),
120120
}
121121
}

checker/patcher.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ func (p *operatorPatcher) Exit(node *ast.Node) {
2323
return
2424
}
2525

26-
leftType := binaryNode.Left.GetType()
27-
rightType := binaryNode.Right.GetType()
26+
leftType := binaryNode.Left.Type()
27+
rightType := binaryNode.Right.Type()
2828

2929
_, fn, ok := conf.FindSuitableOperatorOverload(fns, p.types, leftType, rightType)
3030
if ok {
3131
newNode := &ast.FunctionNode{
3232
Name: fn,
3333
Arguments: []ast.Node{binaryNode.Left, binaryNode.Right},
3434
}
35-
newNode.SetType((*node).GetType())
36-
newNode.SetLocation((*node).GetLocation())
35+
newNode.SetType((*node).Type())
36+
newNode.SetLocation((*node).Location())
3737
*node = newNode
3838
}
3939
}

compiler/compiler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (c *compiler) emit(op byte, b ...byte) int {
6262
c.bytecode = append(c.bytecode, b...)
6363

6464
for i := 0; i < 1+len(b); i++ {
65-
c.locations = append(c.locations, c.currentNode.GetLocation())
65+
c.locations = append(c.locations, c.currentNode.Location())
6666
}
6767

6868
return current
@@ -178,7 +178,7 @@ func (c *compiler) IdentifierNode(node *ast.IdentifierNode) {
178178
}
179179

180180
func (c *compiler) IntegerNode(node *ast.IntegerNode) {
181-
t := node.GetType()
181+
t := node.Type()
182182
if t == nil {
183183
c.emitPush(node.Value)
184184
return
@@ -632,7 +632,7 @@ func encode(i uint16) []byte {
632632
}
633633

634634
func kind(node ast.Node) reflect.Kind {
635-
t := node.GetType()
635+
t := node.Type()
636636
if t == nil {
637637
return reflect.Invalid
638638
}

expr_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func ExampleEval_error() {
9494

9595
fmt.Printf("%v", output)
9696

97-
// Output: syntax error: mismatched input ']' expecting ')' (1:11)
97+
// Output: unexpected token Bracket("]") (1:11)
9898
// | (boo + bar]
9999
// | ..........^
100100
}
@@ -108,9 +108,9 @@ func ExampleEval_matches() {
108108

109109
fmt.Printf("%v", output)
110110

111-
// Output: error parsing regexp: missing closing ): `a(` (1:13)
111+
// Output: error parsing regexp: missing closing ): `a(` (1:17)
112112
// | "a" matches "a("
113-
// | ............^
113+
// | ................^
114114
}
115115

116116
func ExampleCompile() {

file/error.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ func (e *Error) Error() string {
2727
return e.Message
2828
}
2929

30-
func (e *Error) Format(source *Source) error {
30+
func (e *Error) Format(source *Source) string {
3131
if e.Location.Empty() {
32-
return fmt.Errorf(e.Message)
32+
return e.Message
3333
}
3434
var result = fmt.Sprintf(
3535
"%s (%d:%d)",
@@ -58,5 +58,5 @@ func (e *Error) Format(source *Source) error {
5858
}
5959
result += srcLine + indLine
6060
}
61-
return fmt.Errorf(result)
61+
return result
6262
}

optimizer/optimizer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (*inArray) Exit(node *Node) {
4747
if n.Operator == "in" || n.Operator == "not in" {
4848
if array, ok := n.Right.(*ArrayNode); ok {
4949
if len(array.Nodes) > 0 {
50-
t := n.Left.GetType()
50+
t := n.Left.Type()
5151
if t == nil || t.Kind() != reflect.Int {
5252
// This optimization can be only performed if left side is int type,
5353
// as runtime.in func uses reflect.Map.MapIndex and keys of map must,
@@ -251,7 +251,7 @@ func (*constRange) Exit(node *Node) {
251251
}
252252

253253
func patch(node *Node, newNode Node) {
254-
newNode.SetType((*node).GetType())
255-
newNode.SetLocation((*node).GetLocation())
254+
newNode.SetType((*node).Type())
255+
newNode.SetLocation((*node).Location())
256256
*node = newNode
257257
}

parser/lexer/lexer.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ func Lex(source *file.Source) ([]Token, error) {
1717
state = state(l)
1818
}
1919

20-
if l.err == nil {
21-
return l.tokens, nil
20+
if l.err != nil {
21+
return nil, fmt.Errorf("%v", l.err.Format(source))
2222
}
2323

24-
return nil, l.err.Format(source)
24+
return l.tokens, nil
2525
}
2626

2727
type lexer struct {
@@ -62,7 +62,7 @@ func (l *lexer) emit(t Kind) {
6262

6363
func (l *lexer) emitValue(t Kind, value string) {
6464
l.tokens = append(l.tokens, Token{
65-
Location: l.loc(),
65+
Location: l.loc(l.start),
6666
Kind: t,
6767
Value: value,
6868
})
@@ -105,17 +105,17 @@ func (l *lexer) acceptWord(word string) bool {
105105
func (l *lexer) error(format string, args ...interface{}) stateFn {
106106
if l.err == nil { // show first error
107107
l.err = &file.Error{
108-
Location: l.loc(),
108+
Location: l.loc(l.end - 1),
109109
Message: fmt.Sprintf(format, args...),
110110
}
111111
}
112112
return nil
113113
}
114114

115-
func (l *lexer) loc() file.Location {
115+
func (l *lexer) loc(pos int) file.Location {
116116
line, column := 1, 0
117117
for i, ch := range []rune(l.input) {
118-
if i == l.end-1 {
118+
if i == pos {
119119
break
120120
}
121121
if ch == '\n' {

parser/lexer/lexer_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type lexErrorTest struct {
2020

2121
var lexTests = []lexTest{
2222
{
23-
".5 1 02 1e3 0xFF 1.2e-4 1_000_000 _42",
23+
".5 1 02 1e3 0xFF 1.2e-4 1_000_000 _42 -.5",
2424
[]Token{
2525
{Kind: Number, Value: ".5"},
2626
{Kind: Number, Value: "1"},
@@ -30,6 +30,8 @@ var lexTests = []lexTest{
3030
{Kind: Number, Value: "1.2e-4"},
3131
{Kind: Number, Value: "1_000_000"},
3232
{Kind: Identifier, Value: "_42"},
33+
{Kind: Operator, Value: "-"},
34+
{Kind: Number, Value: ".5"},
3335
{Kind: EOF},
3436
},
3537
},

parser/lexer/state.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ func root(l *lexer) stateFn {
2828
l.emit(Bracket)
2929
case strings.ContainsRune(")]}", r):
3030
l.emit(Bracket)
31-
case strings.ContainsRune(",?!:%&*+-/<=>^|", r):
32-
l.backup()
33-
return operator
34-
case r == '#':
31+
case strings.ContainsRune("#,?:%+-/", r): // single rune operator
32+
l.emit(Operator)
33+
case strings.ContainsRune("&|!=*<>", r): // possible double rune operator
34+
l.accept("&|=*")
3535
l.emit(Operator)
3636
case r == '.':
3737
l.backup()
@@ -87,13 +87,6 @@ func (l *lexer) scanNumber() bool {
8787
return true
8888
}
8989

90-
func operator(l *lexer) stateFn {
91-
l.next()
92-
l.accept(".|&=*")
93-
l.emit(Operator)
94-
return root
95-
}
96-
9790
func dot(l *lexer) stateFn {
9891
l.next()
9992
if l.accept("0123456789") {

parser/parser.go

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func Parse(input string) (*Tree, error) {
104104
}
105105

106106
if p.err != nil {
107-
return nil, p.err.Format(source)
107+
return nil, fmt.Errorf("%v", p.err.Format(source))
108108
}
109109

110110
return &Tree{
@@ -203,7 +203,7 @@ func (p *parser) parsePrimary() Node {
203203
p.next()
204204
expr := p.parseExpression(op.precedence)
205205
return p.parsePostfixExpression(&UnaryNode{
206-
Base: Base{Loc: token.Location},
206+
Base: Loc(token.Location),
207207
Operator: token.Value,
208208
Node: expr,
209209
})
@@ -447,25 +447,53 @@ func (p *parser) parsePostfixExpression(node Node) Node {
447447

448448
} else if token.Value == "[" {
449449
p.next()
450-
arg := p.parseExpression(0)
451-
if p.current.Is(Operator, ":") {
450+
var from, to Node
451+
452+
if p.current.Is(Operator, ":") { // slice without from [:1]
452453
p.next()
453-
from := arg
454-
to := p.parseExpression(0)
454+
455+
if !p.current.Is(Bracket, "]") { // slice without from and to [:]
456+
to = p.parseExpression(0)
457+
}
458+
455459
node = &SliceNode{
456460
Base: Loc(p.current.Location),
457461
Node: node,
458-
From: from,
459462
To: to,
460463
}
464+
p.expect(Bracket, "]")
465+
461466
} else {
462-
node = &IndexNode{
463-
Base: Loc(token.Location),
464-
Node: node,
465-
Index: arg,
467+
468+
from = p.parseExpression(0)
469+
470+
if p.current.Is(Operator, ":") {
471+
p.next()
472+
473+
if !p.current.Is(Bracket, "]") { // slice without to [1:]
474+
to = p.parseExpression(0)
475+
}
476+
477+
node = &SliceNode{
478+
Base: Loc(p.current.Location),
479+
Node: node,
480+
From: from,
481+
To: to,
482+
}
483+
p.expect(Bracket, "]")
484+
485+
} else {
486+
// Slice operator [:] was not found, it should by just index node.
487+
488+
node = &IndexNode{
489+
Base: Loc(token.Location),
490+
Node: node,
491+
Index: from,
492+
}
493+
p.expect(Bracket, "]")
466494
}
467495
}
468-
p.expect(Bracket, "]")
496+
469497
} else {
470498
break
471499
}

parser/parser_test.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,18 @@ func TestParse(t *testing.T) {
198198
"array[1:2]",
199199
&ast.SliceNode{Node: &ast.IdentifierNode{Value: "array"}, From: &ast.IntegerNode{Value: 1}, To: &ast.IntegerNode{Value: 2}},
200200
},
201+
{
202+
"array[:2]",
203+
&ast.SliceNode{Node: &ast.IdentifierNode{Value: "array"}, To: &ast.IntegerNode{Value: 2}},
204+
},
205+
{
206+
"array[1:]",
207+
&ast.SliceNode{Node: &ast.IdentifierNode{Value: "array"}, From: &ast.IntegerNode{Value: 1}},
208+
},
209+
{
210+
"array[:]",
211+
&ast.SliceNode{Node: &ast.IdentifierNode{Value: "array"}},
212+
},
201213
}
202214
for _, test := range parseTests {
203215
actual, err := parser.Parse(test.input)
@@ -215,14 +227,14 @@ func TestParse(t *testing.T) {
215227

216228
const errorTests = `
217229
foo.
218-
unexpected end of expression (1:4)
230+
unexpected end of expression (1:5)
219231
| foo.
220-
| ...^
232+
| ....^
221233
222234
a+
223-
unexpected token EOF (1:2)
235+
unexpected token EOF (1:3)
224236
| a+
225-
| .^
237+
| ..^
226238
227239
a ? (1+2) c
228240
unexpected token Identifier("c") (1:11)
@@ -245,9 +257,9 @@ a map key must be a quoted string, a number, a identifier, or an expression encl
245257
| .^
246258
247259
a matches 'a:)b'
248-
error parsing regexp: unexpected ): ` + "`a:)b`" + ` (1:16)
260+
error parsing regexp: unexpected ): ` + "`a:)b`" + ` (1:17)
249261
| a matches 'a:)b'
250-
| ...............^
262+
| ................^
251263
252264
foo({.bar})
253265
a map key must be a quoted string, a number, a identifier, or an expression enclosed in parentheses (unexpected token Operator(".")) (1:6)

0 commit comments

Comments
 (0)