/
genes.go
100 lines (90 loc) · 1.62 KB
/
genes.go
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
94
95
96
97
98
99
100
package main
import (
"bytes"
"fmt"
"github.com/mg/i"
"github.com/mg/i/hoi"
"math"
"os"
"regexp"
)
type gene struct {
atEnd bool
data []interface{}
cur string
}
func Gene(pattern string) i.Forward {
r := regexp.MustCompile("[()]")
tokens := r.Split(pattern, -1)
g := gene{atEnd: false, data: make([]interface{}, 0, len(tokens))}
for i, v := range tokens {
if math.Mod(float64(i), 2) == 0 {
// constant
if v != "" {
g.data = append(g.data, v)
}
} else {
// option
if v != "" {
option := make([]interface{}, 0, len(v)+1)
option = append(option, 0)
for _, c := range v {
option = append(option, string(c))
}
g.data = append(g.data, option)
}
}
}
g.Next()
return &g
}
func (g *gene) Error() error {
return nil
}
func (g *gene) SetError(err error) {
}
func (g *gene) Value() interface{} {
return g.cur
}
func (g *gene) AtEnd() bool {
return g.cur == ""
}
func (g *gene) Next() error {
if g.atEnd {
g.cur = ""
return nil
}
finishedIncr := false
var result bytes.Buffer
for _, t := range g.data {
if v, ok := t.(string); ok {
result.WriteString(v)
} else if v, ok := t.([]interface{}); ok {
n := v[0].(int)
result.WriteString(v[n+1].(string))
if !finishedIncr {
if n == len(v)-2 {
v[0] = 0
} else {
v[0] = v[0].(int) + 1
finishedIncr = true
}
}
}
}
g.atEnd = !finishedIncr
g.cur = result.String()
return nil
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage %s PATTERN\n", os.Args[0])
os.Exit(0)
}
hoi.Each(
Gene(os.Args[1]),
func(itr i.Iterator) bool {
fmt.Println(itr.Value())
return true
})
}