82 lines
2 KiB
Go
82 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Enhanced math expression parser
|
|
func parseMathExpression(query string) (string, bool) {
|
|
// Clean and normalize the expression
|
|
query = strings.ReplaceAll(query, " ", "")
|
|
query = strings.ReplaceAll(query, ",", "")
|
|
|
|
// Regex to match valid math expressions
|
|
mathRegex := regexp.MustCompile(`^\d+(\.\d+)?([\+\-\*/\^]\d+(\.\d+)?)+$`)
|
|
if !mathRegex.MatchString(query) {
|
|
return "", false
|
|
}
|
|
|
|
// Operator precedence handling
|
|
operators := []struct {
|
|
symbol string
|
|
apply func(float64, float64) float64
|
|
}{
|
|
{"^", func(a, b float64) float64 {
|
|
result := 1.0
|
|
for i := 0; i < int(b); i++ {
|
|
result *= a
|
|
}
|
|
return result
|
|
}},
|
|
{"*", func(a, b float64) float64 { return a * b }},
|
|
{"/", func(a, b float64) float64 { return a / b }},
|
|
{"+", func(a, b float64) float64 { return a + b }},
|
|
{"-", func(a, b float64) float64 { return a - b }},
|
|
}
|
|
|
|
// Parse numbers and operators
|
|
var tokens []interface{}
|
|
current := ""
|
|
for _, char := range query {
|
|
if char >= '0' && char <= '9' || char == '.' {
|
|
current += string(char)
|
|
} else {
|
|
if current != "" {
|
|
num, _ := strconv.ParseFloat(current, 64)
|
|
tokens = append(tokens, num)
|
|
current = ""
|
|
}
|
|
tokens = append(tokens, string(char))
|
|
}
|
|
}
|
|
if current != "" {
|
|
num, _ := strconv.ParseFloat(current, 64)
|
|
tokens = append(tokens, num)
|
|
}
|
|
|
|
// Evaluate expression with operator precedence
|
|
for _, op := range operators {
|
|
for i := 1; i < len(tokens)-1; i += 2 {
|
|
if operator, ok := tokens[i].(string); ok && operator == op.symbol {
|
|
left := tokens[i-1].(float64)
|
|
right := tokens[i+1].(float64)
|
|
result := op.apply(left, right)
|
|
|
|
// Update tokens
|
|
tokens = append(tokens[:i-1], tokens[i+2:]...)
|
|
tokens = append(tokens[:i-1], append([]interface{}{result}, tokens[i-1:]...)...)
|
|
i -= 2 // Adjust index after modification
|
|
}
|
|
}
|
|
}
|
|
|
|
// Format result
|
|
result := tokens[0].(float64)
|
|
if result == float64(int(result)) {
|
|
return fmt.Sprintf("%d", int(result)), true
|
|
}
|
|
return fmt.Sprintf("%.2f", result), true
|
|
}
|