-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmath.go
265 lines (240 loc) · 5.97 KB
/
math.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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
package gisp
import (
"fmt"
"reflect"
px "github.com/Dwarfartisan/goparsec/parsex"
)
// TypeMatchError 定了类型匹配错误
type TypeMatchError struct {
Value interface{}
Type reflect.Type
}
func (err TypeMatchError) Error() string {
return fmt.Sprintf("%v not match type %v", err.Value, err.Type)
}
// NotIntError 定了预期为整型但是校验失败的错误
type NotIntError struct {
Value interface{}
}
func (err NotIntError) Error() string {
return fmt.Sprintf("%v is't a valid Int", err.Value)
}
// NotFloatError 定义了预期为浮点数但是校验失败的错误
type NotFloatError struct {
Value interface{}
}
func (err NotFloatError) Error() string {
return fmt.Sprintf("%v is't a valid Float", err.Value)
}
// NotNumberError 定义了预期为数值但是校验失败的错误
type NotNumberError struct {
Value interface{}
}
func (err NotNumberError) Error() string {
return fmt.Sprintf("%v is't a valid Number", err.Value)
}
// IntValue 将所有整型处理为 Int ,其它类型不接受
func IntValue(st px.ParsexState) (interface{}, error) {
v, err := st.Next(px.Always)
if err != nil {
return nil, err
}
switch val := v.(type) {
case int:
return Int(val), nil
case int8:
return Int(val), nil
case int16:
return Int(val), nil
case int32:
return Int(val), nil
case int64:
return Int(val), nil
case Int:
return val, nil
default:
return nil, NotIntError{v}
}
}
// FloatValue 将所有浮点型处理为 Float ,其它类型不接受
func FloatValue(st px.ParsexState) (interface{}, error) {
v, err := st.Next(px.Always)
if err != nil {
return nil, err
}
switch val := v.(type) {
case float32:
return Float(val), nil
case float64:
return Float(val), nil
case Float:
return val, nil
default:
return nil, NotFloatError{v}
}
}
// NumberValue 将所有整型和浮点型处理为 Float ,其它类型不接受
func NumberValue(st px.ParsexState) (interface{}, error) {
v, err := st.Next(px.Always)
if err != nil {
return nil, err
}
switch val := v.(type) {
case int:
return Float(val), nil
case int8:
return Float(val), nil
case int16:
return Float(val), nil
case int32:
return Float(val), nil
case int64:
return Float(val), nil
case Int:
return Float(val), nil
case float32:
return Float(val), nil
case float64:
return Float(val), nil
case Float:
return val, nil
default:
return nil, NotNumberError{v}
}
}
// Int2Values 获取多个 int
var Int2Values = px.Bind(IntValue, func(x interface{}) px.Parser {
return func(st px.ParsexState) (interface{}, error) {
y, err := IntValue(st)
if err != nil {
return nil, err
}
return []interface{}{x, y}, nil
}
})
// Num2Values 获取多个 int
var Num2Values = px.Bind(NumberValue, func(x interface{}) px.Parser {
return func(st px.ParsexState) (interface{}, error) {
y, err := NumberValue(st)
if err != nil {
return nil, err
}
return []interface{}{x, y}, nil
}
})
func xEOF(x interface{}) px.Parser {
return px.Bind_(px.Eof, px.Return(x))
}
// addx 实现一个parsex累加解析器,精度向上适配。我一直觉得应该有一个简单的高效版本,不需要回溯的
// 但是目前还没有找到。
func addx(st px.ParsexState) (interface{}, error) {
ints, err := px.Try(px.ManyTil(IntValue, px.Eof))(st)
if err == nil {
root := Int(0)
for _, x := range ints.([]interface{}) {
root += x.(Int)
}
return root, nil
}
numbers, err := px.ManyTil(NumberValue, px.Eof)(st)
if err == nil {
root := Float(0)
for _, x := range numbers.([]interface{}) {
root += x.(Float)
}
return root, nil
}
if nerr, ok := err.(NotNumberError); ok {
return nil, TypeSignError{Type: FLOATMUST, Value: nerr.Value}
}
return nil, err
}
func addInts(ints ...interface{}) (interface{}, error) {
root := ints[0].(Int)
for _, i := range ints[1:] {
root += i.(Int)
}
return root, nil
}
func addFloats(floats ...interface{}) (interface{}, error) {
root := floats[0].(Float)
for _, f := range floats[1:] {
root += f.(Float)
}
return root, nil
}
// subx 实现一个左折叠的 parsex 连减解析器,精度向上适配。
func subx(st px.ParsexState) (interface{}, error) {
data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st)
if err == nil {
ints := data.([]interface{})
root := ints[0].(Int)
for _, x := range ints[1:] {
root -= x.(Int)
}
return root, nil
}
data, err = px.ManyTil(NumberValue, px.Eof)(st)
if err == nil {
numbers := data.([]interface{})
root := numbers[0].(Float)
for _, x := range numbers[1:] {
root -= x.(Float)
}
return root, nil
}
if nerr, ok := err.(NotNumberError); ok {
return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value}
}
return nil, err
}
// mulx 实现一个 parsex 累乘解析器,精度向上适配。
func mulx(st px.ParsexState) (interface{}, error) {
data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st)
if err == nil {
ints := data.([]interface{})
root := ints[0].(Int)
for _, x := range ints[1:] {
root *= x.(Int)
}
return root, nil
}
data, err = px.ManyTil(NumberValue, px.Eof)(st)
if err == nil {
numbers := data.([]interface{})
root := numbers[0].(Float)
for _, x := range numbers[1:] {
root *= x.(Float)
}
return root, nil
}
if nerr, ok := err.(NotNumberError); ok {
return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value}
}
return nil, err
}
// divx 实现一个左折叠的 parsex 连除解析器,精度向上适配。
func divx(st px.ParsexState) (interface{}, error) {
data, err := px.Try(px.ManyTil(IntValue, px.Eof))(st)
if err == nil {
ints := data.([]interface{})
root := ints[0].(Int)
for _, x := range ints[1:] {
root /= x.(Int)
}
return root, nil
}
data, err = px.ManyTil(NumberValue, px.Eof)(st)
if err == nil {
numbers := data.([]interface{})
root := numbers[0].(Float)
for _, x := range numbers[1:] {
root /= x.(Float)
}
return root, nil
}
if nerr, ok := err.(NotNumberError); ok {
return nil, TypeSignError{Type: Type{FLOAT, false}, Value: nerr.Value}
}
return nil, err
}