-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbracket.go
222 lines (203 loc) · 5.91 KB
/
bracket.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package gisp
import (
"fmt"
"reflect"
p "github.com/Dwarfartisan/goparsec"
px "github.com/Dwarfartisan/goparsec/parsex"
)
// Bracket 实现中括号表达式的解析,包括序列索引、切割,字典的key查找
type Bracket struct {
obj interface{}
expr []interface{}
}
// Eval 方法实现 Bracket 表达式的求值
func (bracket Bracket) Eval(env Env) (interface{}, error) {
obj, err := Eval(env, bracket.obj)
if err != nil {
return nil, err
}
val := reflect.ValueOf(obj)
switch val.Kind() {
case reflect.Slice, reflect.String, reflect.Array:
switch len(bracket.expr) {
case 1:
return bracket.evalIndex(env, val)
case 2, 3:
return bracket.evalSlice(env, val)
default:
return nil, fmt.Errorf("Unknow howto index or slice:%v[%v]",
bracket.obj, bracket.expr)
}
case reflect.Map:
if len(bracket.expr) == 1 {
key := reflect.ValueOf(bracket.expr[0])
v := val.MapIndex(key)
return bracket.inter(v), nil
}
return nil, fmt.Errorf("Unknow howto parse map %v[%v]",
bracket.obj, bracket.expr)
}
return nil, fmt.Errorf("Unknow howto parse formal as %v[%v]",
bracket.obj, bracket.expr)
}
func (bracket Bracket) inter(value reflect.Value) interface{} {
if value.IsValid() {
return Value(value.Interface())
}
return nil
}
func (bracket Bracket) evalIndex(env Env, val reflect.Value) (interface{}, error) {
i, err := Eval(env, bracket.expr[0])
if err != nil {
return nil, err
}
if idx, ok := i.(Int); ok {
v := val.Index(int(idx))
return bracket.inter(v), nil
}
return nil, fmt.Errorf("Index for slice %v[%v] is invalid data: %v",
bracket.obj, bracket.expr, i)
}
func (bracket Bracket) evalSlice(env Env, val reflect.Value) (interface{}, error) {
items, err := Evals(env, bracket.expr...)
if err != nil {
return nil, err
}
indexs, err := bracket.computeIndexs(val, items)
if err != nil {
return nil, err
}
switch len(indexs) {
case 2:
v := val.Slice(indexs[0], indexs[1])
return bracket.inter(v), nil
case 3:
v := val.Slice3(indexs[0], indexs[1], indexs[2])
return bracket.inter(v), nil
}
return nil, fmt.Errorf("Index for slice %v[%v] is invalid",
bracket.obj, bracket.expr)
}
func (bracket Bracket) computeIndexs(val reflect.Value, input []interface{}) ([]int, error) {
indexs := make([]int, len(input))
for idx, item := range input {
if idx < 2 {
i, err := bracket.computeIndex(val, item)
if err != nil {
return nil, err
}
indexs[idx] = i
}
}
return indexs, nil
}
func (bracket Bracket) computeIndex(val reflect.Value, input interface{}) (int, error) {
l := val.Len()
if index, ok := input.(Int); ok {
i := int(index)
if i < 0 {
i = l - i
}
if i < 0 || i > l-1 {
return 0, fmt.Errorf("Try to slice %v[%v] but %v out range",
bracket.obj, bracket.expr, index)
}
return i, nil
}
return 0, fmt.Errorf("Try to slice %v[%v] but %v is invalid",
bracket.obj, bracket.expr, input)
}
// SetItemBy 根据传值对括号表达式引用的容器进行写操作,即 col[x] = y => (set col[x] y)
func (bracket Bracket) SetItemBy(env Env, item interface{}) (interface{}, error) {
obj, err := Eval(env, bracket.obj)
if err != nil {
return nil, err
}
val := reflect.ValueOf(obj)
switch val.Kind() {
case reflect.Map:
return bracket.SetMapIndex(val, env, item)
case reflect.Slice:
return bracket.SetSliceIndex(val, env, item)
default:
return nil, fmt.Errorf("Excpet %v[%v]=%v but %v is neither slice nor map",
obj, item, bracket.expr, obj)
}
}
// SetMapIndex 是给 Map 类型写入键值的特化实现
func (bracket Bracket) SetMapIndex(val reflect.Value, env Env, item interface{}) (interface{}, error) {
if len(bracket.expr) != 1 {
return nil, fmt.Errorf("Excpet %v[%v]=%v but %v has error items(only accept one key)",
val.Interface(), bracket.expr, item, bracket.expr)
}
k, err := Eval(env, bracket.expr[0])
if err != nil {
return nil, err
}
key := reflect.ValueOf(k)
value := reflect.ValueOf(item)
val.SetMapIndex(key, value)
return val.Interface(), nil
}
// SetSliceIndex 是为线性序列切片进行写操作的实现
func (bracket Bracket) SetSliceIndex(val reflect.Value, env Env, item interface{}) (interface{}, error) {
if len(bracket.expr) < 1 {
return nil, fmt.Errorf("excpet %v[%v]=%v but %v has error items(only accept one or two key)",
val.Interface(), bracket.expr, item, bracket.expr)
}
item, err := Eval(env, bracket.expr[0])
if err != nil {
return nil, err
}
index, err := bracket.computeIndex(val, item)
if err != nil {
return nil, err
}
value := reflect.ValueOf(item)
val.Index(index).Set(value)
return val.Interface(), nil
}
// IntVal 尝试将 state 中的下一个数据解为 int
func IntVal(st px.ParsexState) (interface{}, error) {
x, err := st.Next(px.Always)
if err != nil {
return nil, err
}
if _, ok := x.(Int); ok {
return x, nil
}
return nil, fmt.Errorf("except a Int value but got %v", x)
}
// BracketParser 尝试将 state 中下一个值解析为中括号表达式
func BracketParser(st p.ParseState) (interface{}, error) {
return p.Between(p.Rune('['), p.Rune(']'),
p.SepBy1(ValueParser, p.Rune(':')),
)(st)
}
// BracketParserExt 在带有 Ext 的环境下对中括号表达式求值
func BracketParserExt(env Env) p.Parser {
return p.Between(p.Rune('['), p.Rune(']'),
p.SepBy1(ValueParserExt(env), p.Rune(':')),
)
}
//BracketExpr 结构实现中括号表达式的
type BracketExpr struct {
Expr []interface{}
}
// Task 的实现会返回 Bracket 对象
func (be BracketExpr) Task(env Env, args ...interface{}) (Lisp, error) {
if len(args) != 1 {
return nil, ParsexSignErrorf("Bracket Expression Args Error: except a arg but %v", args)
}
return Bracket{args[0], be.Expr}, nil
}
// BracketExprParserExt 返回带 Ext 环境的 BracketExpr 。
func BracketExprParserExt(env Env) p.Parser {
return func(st p.ParseState) (interface{}, error) {
expr, err := BracketParserExt(env)(st)
if err != nil {
return nil, err
}
return BracketExpr{expr.([]interface{})}, nil
}
}