-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexample_test.go
More file actions
93 lines (78 loc) · 2.07 KB
/
Copy pathexample_test.go
File metadata and controls
93 lines (78 loc) · 2.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package parse
import (
"fmt"
"testing"
"github.com/ohait/forego/test"
)
type Op interface {
}
type BinOp struct {
Left Op
Op string
Right Op
}
func (this BinOp) String() string {
return fmt.Sprintf("❲%v%s%v❳", this.Left, this.Op, this.Right)
}
type Lit struct {
Val string // true, 123, 1.34, "foo"
}
func (this Lit) String() string {
return fmt.Sprintf("%v", this.Val)
}
func TestManualAssoc(t *testing.T) {
var g Grammar
g.Alt("add").Add(`lit add_`, func(op Op, list []BinOp) (any, error) {
for _, n := range list {
n.Left = op
op = n
}
return op, nil
})
g.Add("add_", `/[\+\-]/ lit add_`).Return(func(op string, lit any, extra []BinOp) []BinOp {
return append([]BinOp{{Op: op, Right: lit}}, extra...)
})
g.Add("add_", ``).Return(func() []BinOp { return nil })
g.Add("lit", `/\d+/`).Return(func(v string) any { return Lit{v} })
test.NoError(t, g.Verify())
out, _, err := g.Parse("add", []byte(`1+2+3`))
test.NoError(t, err)
t.Logf("%+v", out)
}
func TestGrammar(t *testing.T) {
var g Grammar
g.Log = t.Logf
g.Add("expr", `cmp`)
g.Add("cmp", `add /(<|<=|==|>-|>|!=)/ add`).Return(func(l Op, op string, r Op) BinOp {
return BinOp{Left: l, Op: op, Right: r}
})
g.Add("cmp", `add`)
g.Add("add", `mul /[\+\-]/ add`).Return(func(l Op, op string, r Op) BinOp {
return BinOp{Left: l, Op: op, Right: r}
})
g.Add("add", `mul`)
g.Add("mul", `lit /[\*\/]/ mul`).Return(func(l Op, op string, r Op) BinOp {
return BinOp{Left: l, Op: op, Right: r}
})
g.Add("mul", `lit`)
g.Add("lit", `/\d+/`).Return(func(v string) Lit { return Lit{v} })
g.Add("lit", `/\d*\.\d*/`).Return(func(v string) Lit { return Lit{v} })
g.Add("lit", `/"([^"]|".)*"/`).Return(func(v string) Lit { return Lit{v} })
test.NoError(t, g.Verify())
t.Logf("lit: %+v", g.alts["lit"].prods[0])
{
out, _, err := g.Parse("expr", []byte("1+2"))
test.NoError(t, err)
t.Logf("%+v", out)
}
{
out, _, err := g.Parse("expr", []byte("1+3*2"))
test.NoError(t, err)
t.Logf("%+v", out)
}
{
out, _, err := g.Parse("expr", []byte("1+2+3"))
test.NoError(t, err)
t.Logf("%+v", out)
}
}