-
Notifications
You must be signed in to change notification settings - Fork 0
/
expressUtil.go
203 lines (190 loc) · 5.86 KB
/
expressUtil.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
/*
@Time : 2019/10/19 10:25
@Author : Hermes
@File : splitExpress
@Description:
*/
package calculator
import (
"bytes"
"fmt"
"github.com/xukgo/gsaber/utils/ruleUtil"
"github.com/xukgo/gsaber/utils/stringUtil"
"strconv"
)
//把表达式分解成数字和符号,过程中自动校验数字是否是浮点数,自动调整一些符号比如开头和括号后开头的+-
func calcExpressSplit(exp string, signs []string) ([]*calcMinor, error) {
var err error
var arr []*calcMinor
srclen := len(exp)
leftBracketCount := 0
rightBracketCount := 0
var first bool = true
index := 0 //代表src指针目前的偏移
lastSign := "" //代表上个是符号,不是则置为空
bf := new(bytes.Buffer)
for i := 0; i < srclen; i++ {
signLen := 0
matchSign := ""
for idx := range signs {
if stringUtil.StartWithIndex(exp, index, signs[idx]) {
matchSign = signs[idx]
signLen = len(matchSign)
break
}
}
if signLen == 0 {
bf.WriteByte(exp[i])
index++
lastSign = ""
} else {
if bf.Len() > 0 {
numberVal := bf.String()
if !ruleUtil.CheckIsFloat(numberVal) {
return nil, fmt.Errorf("表达式内不是有效的数值类型:%s", numberVal)
}
fval, err := strconv.ParseFloat(numberVal, 64)
if err != nil {
return nil, fmt.Errorf("表达式内不是有效的数值类型:%s", numberVal)
}
arr = append(arr, newCalcMinorItem(TYPE_NUMBER, fval))
bf.Reset()
}
arr, err = handlerSign(arr, bf, first, lastSign, matchSign)
if err != nil {
return nil, err
}
if matchSign == "(" {
leftBracketCount++
} else if matchSign == ")" {
rightBracketCount++
}
index += signLen
lastSign = matchSign
}
first = false
}
//结尾后处理,如果是数字还要加进去
if bf.Len() > 0 {
numberVal := bf.String()
if !ruleUtil.CheckIsFloat(numberVal) {
return nil, fmt.Errorf("表达式内不是有效的数值类型:%s", numberVal)
}
fval, err := strconv.ParseFloat(numberVal, 64)
if err != nil {
return nil, fmt.Errorf("表达式内不是有效的数值类型:%s", numberVal)
}
arr = append(arr, newCalcMinorItem(TYPE_NUMBER, fval))
//bf.Reset()
} else {
if len(arr) > 0 {
//验证最后一个如果是符号,是否合法,最后结尾只允许)
lastMinor := arr[len(arr)-1]
if lastMinor.Val != ")" {
return nil, fmt.Errorf("表达式最后结尾作为符号只允许)")
}
}
}
//验证()数量对应
if leftBracketCount != rightBracketCount {
return nil, fmt.Errorf("左括号和右括号的数量不匹配")
}
return arr, nil
}
func handlerSign(arr []*calcMinor, bf *bytes.Buffer, first bool, lastSign string, matchSign string) ([]*calcMinor, error) {
if matchSign == "+" {
//这些情况忽略+
if first || lastSign == "*" || lastSign == "/" || lastSign == "(" {
//忽略
} else if lastSign == "+" || lastSign == "-" { //这些情况不允许,报错
return nil, fmt.Errorf("请检查表达式,不允许+-叠加在一起")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
} else if matchSign == "-" {
//这些情况入数值缓存
if first || lastSign == "*" || lastSign == "/" || lastSign == "(" {
bf.WriteString(matchSign)
} else if lastSign == "+" || lastSign == "-" { //这些情况不允许,报错
return nil, fmt.Errorf("请检查表达式,不允许+-叠加在一起")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
} else if matchSign == "*" {
if first {
return nil, fmt.Errorf("请检查表达式,不允许以*开始")
} else if lastSign == "*" || lastSign == "/" || lastSign == "+" || lastSign == "-" || lastSign == "(" {
return nil, fmt.Errorf("请检查表达式,不允许非法符号叠加")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
} else if matchSign == "/" {
if first {
return nil, fmt.Errorf("请检查表达式,不允许以/开始")
} else if lastSign == "*" || lastSign == "/" || lastSign == "+" || lastSign == "-" || lastSign == "(" {
return nil, fmt.Errorf("请检查表达式,不允许非法符号叠加")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
} else if matchSign == "(" {
if lastSign == ")" {
return nil, fmt.Errorf("请检查表达式,不允许非法符号叠加")
} else if !first && lastSign == "" {
return nil, fmt.Errorf("请检查表达式,不允许数值后面直接接(")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
} else if matchSign == ")" {
if first {
return nil, fmt.Errorf("请检查表达式,不允许符号)开始")
} else if lastSign == "(" || lastSign == "+" || lastSign == "-" || lastSign == "*" || lastSign == "/" {
return nil, fmt.Errorf("请检查表达式,不允许非法符号叠加")
} else { // ")"正常入队
arr = append(arr, newCalcMinorItem(TYPE_SIGN, matchSign))
}
}
return arr, nil
}
//
////验证和调整表达式分解后的顺序合法
//func checkAndAdaptExpressSplits(minors []*calcMinor) ([]*calcMinor, error) {
// var delIndexArr []int
// var lastSign string
// var currentSign string
// if checkIsSign(minors[0], "+") {
// delIndexArr = append(delIndexArr, 0)
// }
// if checkIsSign(minors[0], "-") {
// delIndexArr = append(delIndexArr, 0)
// }
// return minors, nil
//}
func checkIsSign(minor *calcMinor, sign string) bool {
if minor.Vtype != TYPE_SIGN {
return false
}
if minor.Val == sign {
return true
}
return false
}
func removeCalcMinorIndex(arr []*calcMinor, index int) []*calcMinor {
j := 0
for idx := range arr {
if idx != index {
arr[j] = arr[idx]
j++
}
}
return arr[:j]
}
func insertCalcMinorIndex(arr []*calcMinor, index int, addItem *calcMinor) []*calcMinor {
j := 0
for idx := range arr {
if idx != index {
arr[j] = arr[idx]
j++
}
}
return arr[:j]
}