Skip to content

Commit 02245cb

Browse files
author
xiachongshang
committedDec 28, 2021
init
0 parents  commit 02245cb

File tree

2 files changed

+283
-0
lines changed

2 files changed

+283
-0
lines changed
 

‎CompNode.go

+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
package comp
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
var (
8+
//需要一个全局控制的函数
9+
FuncLi map[string]CompMark
10+
)
11+
12+
const (
13+
//常量:最小的变量索引
14+
Coust_a byte = 97
15+
)
16+
17+
func init() {
18+
FuncLi = make(map[string]CompMark)
19+
}
20+
21+
func RegisterComp(name string, f CompMark) {
22+
FuncLi[name] = f
23+
}
24+
25+
/*
26+
输入字符串;输出运算对象
27+
现在支持+-*/还有自定义的函数
28+
"(a+b*c-4)/rand(6+21,100)"
29+
不支持负号开头
30+
*/
31+
func NewCompNode(exp string) *CompNode {
32+
arr := compStringToArray(exp)
33+
result, _ := createComp(arr)
34+
return result
35+
}
36+
37+
type CompMark func(node *CompNode, arr []int64) int64
38+
39+
//计算对象
40+
type CompNode struct {
41+
Var string //值
42+
Val int64 //值数据
43+
Num1 *CompNode //数据1
44+
Mark string //运算符号
45+
Num2 *CompNode //数据2
46+
}
47+
48+
//循环计算
49+
func (cn *CompNode) CompVal(param []int64) int64 {
50+
51+
if cn.Mark != "" {
52+
return cn.markComp(param)
53+
} else {
54+
return cn.getVal(param)
55+
}
56+
// } else if cn.Mark == "+" || cn.Mark == "-" || cn.Mark == "*" || cn.Mark == "/" {
57+
// return "(" + cn.Num1.String() + " " + cn.Mark + " " + cn.Num2.String() + ")"
58+
// } else {
59+
// return cn.Mark + "(" + cn.Num1.String() + "," + cn.Num2.String() + ")"
60+
// }
61+
}
62+
63+
func (cn *CompNode) String() string {
64+
if cn.Var != "" {
65+
return cn.Var
66+
} else if cn.Mark == "+" || cn.Mark == "-" || cn.Mark == "*" || cn.Mark == "/" || cn.Mark == "%" {
67+
return "(" + cn.Num1.String() + " " + cn.Mark + " " + cn.Num2.String() + ")"
68+
} else if cn.Mark != "" {
69+
return cn.Mark + "(" + cn.Num1.String() + "," + cn.Num2.String() + ")"
70+
} else {
71+
return fmt.Sprint(cn.Val)
72+
}
73+
}
74+
75+
func (cn *CompNode) markComp(arr []int64) (result int64) {
76+
switch cn.Mark {
77+
case "+":
78+
result = cn.Num1.CompVal(arr) + cn.Num2.CompVal(arr)
79+
case "-":
80+
result = cn.Num1.CompVal(arr) - cn.Num2.CompVal(arr)
81+
case "*":
82+
result = cn.Num1.CompVal(arr) * cn.Num2.CompVal(arr)
83+
case "/":
84+
result = cn.Num1.CompVal(arr) / cn.Num2.CompVal(arr)
85+
case "%":
86+
result = cn.Num1.CompVal(arr) % cn.Num2.CompVal(arr)
87+
default:
88+
if f, ok := FuncLi[cn.Mark]; ok {
89+
//找到函数
90+
result = f(cn, arr)
91+
} else {
92+
fmt.Println(" CompNode Error. Not exist Func ", cn.Mark, ". on CompNode:", cn)
93+
}
94+
}
95+
return
96+
}
97+
98+
//拿到值
99+
func (cn *CompNode) getVal(arr []int64) (result int64) {
100+
//使用a,b,c,d,e,f,g来定义变量,所以a对应的就是数组索引0,依次类推
101+
if cn.Var != "" {
102+
//是变量
103+
i := int(cn.Var[0] - Coust_a) //拿到变量索引
104+
if len(arr) > i {
105+
result = arr[i]
106+
}
107+
} else {
108+
result = cn.Val
109+
}
110+
return
111+
}
112+
113+
//运算数据
114+
func compStringToArray(exp string) (result []string) {
115+
arr := []rune(exp)
116+
tmp := NewStringBuilder()
117+
result = make([]string, 0, len(arr))
118+
for len(arr) > 0 {
119+
switch arr[0] {
120+
case '-', '+', '*', '/', '%', '(', ')', ',':
121+
if !tmp.IsEmpty() {
122+
result = append(result, tmp.ToString())
123+
tmp.Clear()
124+
}
125+
result = append(result, string(arr[0]))
126+
default:
127+
tmp.AppendRune(arr[0])
128+
}
129+
arr = arr[1:]
130+
}
131+
if !tmp.IsEmpty() {
132+
result = append(result, tmp.ToString())
133+
}
134+
// fmt.Println(result)
135+
return
136+
}
137+
138+
//算符号优先
139+
func checkPriority(mark string) int {
140+
priority := 10
141+
switch mark {
142+
case "+", "-":
143+
priority = 0
144+
case "*", "/", "%":
145+
priority = 1
146+
147+
}
148+
return priority
149+
}
150+
151+
func newComp(v string) *CompNode {
152+
result := new(CompNode)
153+
if t, ok := NewString(v).ToInt64(); ok == nil {
154+
result.Val = t
155+
} else {
156+
result.Var = v
157+
}
158+
return result
159+
}
160+
161+
//生成运算对象
162+
func createComp(arr []string) (result *CompNode, resarr []string) {
163+
numsk := make(Stack, 0, 20)
164+
marksk := make(StackMark, 0, 20)
165+
arrfor:
166+
for len(arr) > 0 {
167+
data := arr[0]
168+
arr = arr[1:]
169+
if _, ok := FuncLi[data]; ok {
170+
//找到了函数
171+
//函数部分,双参数的部分
172+
marksk.Push(data)
173+
result, resarr = createComp(arr[1:]) //函数都会带括号
174+
numsk.Push(result)
175+
arr = resarr
176+
result, resarr = createComp(arr)
177+
numsk.Push(result)
178+
arr = resarr
179+
} else {
180+
switch data {
181+
case "(":
182+
//要嵌套调用
183+
result, resarr = createComp(arr)
184+
numsk.Push(result)
185+
arr = resarr
186+
case ")", ",":
187+
//结束当前调用
188+
break arrfor
189+
case "-", "+", "*", "/", "%":
190+
//符号
191+
if marksk.Len() == 0 {
192+
marksk.Push(data)
193+
} else {
194+
curpt := checkPriority(data)
195+
for numsk.Len() >= 2 {
196+
propt := checkPriority(marksk.Get())
197+
//优先级
198+
if curpt <= propt {
199+
num2, num1 := numsk.Pop(), numsk.Pop()
200+
mark := marksk.Pop()
201+
cn := new(CompNode)
202+
cn.Num1 = num1
203+
cn.Num2 = num2
204+
cn.Mark = mark
205+
numsk.Push(cn)
206+
} else {
207+
break
208+
}
209+
}
210+
marksk.Push(data)
211+
}
212+
default:
213+
//数值
214+
cn := newComp(data)
215+
numsk.Push(cn)
216+
}
217+
}
218+
219+
}
220+
for numsk.Len() >= 2 {
221+
num2, num1 := numsk.Pop(), numsk.Pop()
222+
mark := marksk.Pop()
223+
cn := new(CompNode)
224+
cn.Num1 = num1
225+
cn.Num2 = num2
226+
cn.Mark = mark
227+
228+
numsk.Push(cn)
229+
}
230+
cn := numsk.Get()
231+
return cn, arr
232+
}
233+
234+
type Stack []*CompNode
235+
236+
func (sk Stack) Len() int {
237+
return len(sk)
238+
}
239+
240+
func (sk *Stack) Push(v *CompNode) {
241+
*sk = append(*sk, v)
242+
}
243+
244+
func (sk *Stack) Pop() (result *CompNode) {
245+
result = (*sk)[sk.Len()-1]
246+
*sk = (*sk)[:sk.Len()-1]
247+
return
248+
}
249+
250+
func (sk Stack) IsEmpty() bool {
251+
return len(sk) == 0
252+
}
253+
254+
func (sk Stack) Get() (result *CompNode) {
255+
return sk[sk.Len()-1]
256+
}
257+
258+
type StackMark []string
259+
260+
func (sk StackMark) Len() int {
261+
return len(sk)
262+
}
263+
264+
func (sk *StackMark) Push(v string) {
265+
*sk = append(*sk, v)
266+
}
267+
268+
func (sk *StackMark) Pop() (result string) {
269+
result = (*sk)[sk.Len()-1]
270+
*sk = (*sk)[:sk.Len()-1]
271+
return
272+
}
273+
274+
func (sk StackMark) IsEmpty() bool {
275+
return len(sk) == 0
276+
}
277+
278+
func (sk StackMark) Get() (result string) {
279+
return sk[sk.Len()-1]
280+
}

‎go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/buguang01/comp
2+
3+
go 1.17

0 commit comments

Comments
 (0)
Please sign in to comment.