-
Notifications
You must be signed in to change notification settings - Fork 2
/
resolve.go
105 lines (98 loc) · 3.41 KB
/
resolve.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
package mathparse
import (
"math"
"strconv"
)
func (p *Parser) Resolve() {
// parenthases
// exponents/roots
// multiplication/division
// addition/subtraction
// functions
// repeat
p.tokens = parseExpression(p.tokens)
}
func parseExpression(set []Token) []Token {
mod := false
if set[0].Type == function || set[0].Type == lparen {
set[0].Children = parseExpression(set[0].Children)
}
for i := 1; i < len(set)-1; i++ {
if set[i].Type == operation {
if (set[i].Value == "^") && (set[i-1].Type == literal && set[i+1].Type == literal) {
mod = true
set[i-1].ParseValue = math.Pow(set[i-1].ParseValue, set[i+1].ParseValue)
set[i-1].Value = strconv.FormatFloat(set[i-1].ParseValue, 'f', -1, 64)
set = append(set[:i], set[i+2:]...)
i--
}
}
}
for i := 1; i < len(set)-1; i++ {
if set[i].Type == operation {
if (set[i].Value == "*" || set[i].Value == "/") && (set[i-1].Type == literal && set[i+1].Type == literal) {
mod = true
if set[i].Value == "*" {
set[i-1].ParseValue = set[i-1].ParseValue * set[i+1].ParseValue
} else if set[i].Value == "/" {
set[i-1].ParseValue = set[i-1].ParseValue / set[i+1].ParseValue
}
set[i-1].Value = strconv.FormatFloat(set[i-1].ParseValue, 'f', -1, 64)
set = append(set[:i], set[i+2:]...)
i--
}
}
}
for i := 1; i < len(set)-1; i++ {
if set[i].Type == operation {
if (set[i].Value == "+" || set[i].Value == "-") && (set[i-1].Type == literal && set[i+1].Type == literal) {
mod = true
if set[i].Value == "+" {
set[i-1].ParseValue = set[i-1].ParseValue + set[i+1].ParseValue
} else if set[i].Value == "-" {
set[i-1].ParseValue = set[i-1].ParseValue - set[i+1].ParseValue
}
set[i-1].Value = strconv.FormatFloat(set[i-1].ParseValue, 'f', -1, 64)
set = append(set[:i], set[i+2:]...)
i--
}
}
}
// functions
for i := range set {
if set[i].Type == lparen {
if len(set[i].Children) == 1 {
set[i] = set[i].Children[0]
}
}
if set[i].Type == function {
mod = true
switch set[i].Value {
case "sin":
set[i] = newToken(literal, strconv.FormatFloat(math.Sin(set[i].Children[0].ParseValue), 'f', -1, 64))
case "cos":
set[i] = newToken(literal, strconv.FormatFloat(math.Cos(set[i].Children[0].ParseValue), 'f', -1, 64))
case "tan":
set[i] = newToken(literal, strconv.FormatFloat(math.Tan(set[i].Children[0].ParseValue), 'f', -1, 64))
case "abs":
set[i] = newToken(literal, strconv.FormatFloat(math.Abs(set[i].Children[0].ParseValue), 'f', -1, 64))
case "log":
set[i] = newToken(literal, strconv.FormatFloat(math.Log(set[i].Children[0].ParseValue), 'f', -1, 64))
case "sqrt":
set[i] = newToken(literal, strconv.FormatFloat(math.Sqrt(set[i].Children[0].ParseValue), 'f', -1, 64))
case "max":
set[i] = newToken(literal, strconv.FormatFloat(math.Max(set[i].Children[0].ParseValue, set[i].Children[2].ParseValue), 'f', -1, 64))
case "min":
set[i] = newToken(literal, strconv.FormatFloat(math.Min(set[i].Children[0].ParseValue, set[i].Children[2].ParseValue), 'f', -1, 64))
case "mod":
set[i] = newToken(literal, strconv.FormatFloat(math.Mod(set[i].Children[0].ParseValue, set[i].Children[2].ParseValue), 'f', -1, 64))
case "pow":
set[i] = newToken(literal, strconv.FormatFloat(math.Pow(set[i].Children[0].ParseValue, set[i].Children[2].ParseValue), 'f', -1, 64))
}
}
}
if len(set) > 1 && mod {
set = parseExpression(set)
}
return set
}