Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package Calc
- import (
- "fmt"
- "os"
- "regexp"
- "strconv"
- "strings"
- )
- func main() {
- expression := os.Args[len(os.Args)-1]
- fmt.Printf("%v", calculator(expression))
- }
- func calculator(expression string) string {
- expression = strings.ReplaceAll(expression, "(", " ( ")
- expression = strings.ReplaceAll(expression, ")", " ) ")
- expression = strings.ReplaceAll(expression, "+", " + ")
- expression = strings.ReplaceAll(expression, "-", " - ")
- expression = strings.ReplaceAll(expression, "*", " * ")
- expression = strings.ReplaceAll(expression, "/", " / ")
- expressionSlice := strings.Split(expression, " ")
- var pureExprSlice []string
- for _, val := range expressionSlice {
- if val != "" {
- pureExprSlice = append(pureExprSlice, val)
- }
- }
- prior := map[string]int{
- "+": 1,
- "-": 1,
- "*": 2,
- "/": 2,
- }
- stackNumbers, stackOperators := Stack{}, Stack{}
- for i := 0; i < len(pureExprSlice); i++ {
- currToken := pureExprSlice[i] //текущий токен
- validTokSymb := regexp.MustCompile("^[+-/*)(]$") //оператор или скобка
- validTokNumb := regexp.MustCompile("^[0-9]*$") //число
- if validTokSymb.MatchString(currToken) || validTokNumb.MatchString(currToken) {
- switch currToken {
- case "(":
- stackOperators.Push(currToken)
- case ")":
- topStackOperand := stackOperators.Top()
- if topStackOperand == "(" {
- stackOperators.Pop()
- } else {
- i--
- makeOperation(&stackNumbers, &stackOperators)
- }
- case "-", "+", "*", "/":
- if stackOperators.Len() == 0 || stackOperators.Top() == "(" || stackOperators.Top() == ")" ||
- prior[currToken] > prior[stackOperators.Top().(string)] {
- stackOperators.Push(currToken)
- } else {
- i--
- makeOperation(&stackNumbers, &stackOperators)
- }
- default:
- stackNumbers.Push(currToken)
- }
- } else {
- return "Incorrect data"
- }
- }
- for stackOperators.Len() != 0 {
- makeOperation(&stackNumbers, &stackOperators)
- }
- return stackNumbers.Top().(string)
- }
- func makeOperation(stackNumbers *Stack, stackOperators *Stack) {
- operand1String := stackNumbers.Pop().(string)
- operand1, err := strconv.Atoi(operand1String)
- if err != nil {
- os.Exit(1)
- }
- operand2String := stackNumbers.Pop().(string)
- operand2, err := strconv.Atoi(operand2String)
- if err != nil {
- os.Exit(1)
- }
- switch stackOperators.Pop() {
- case "+":
- stackNumbers.Push(strconv.Itoa(operand1 + operand2))
- case "-":
- stackNumbers.Push(strconv.Itoa(operand2 - operand1))
- case "*":
- stackNumbers.Push(strconv.Itoa(operand1 * operand2))
- case "/":
- stackNumbers.Push(strconv.Itoa(operand1 / operand2))
- }
- }
- type Stack struct {
- top *Element
- size int
- }
- type Element struct {
- value interface{}
- next *Element
- }
- func (s *Stack) Len() int {
- return s.size
- }
- func (s *Stack) Push(value interface{}) {
- s.top = &Element{value, s.top}
- s.size++
- }
- func (s *Stack) Pop() (value interface{}) {
- if s.size > 0 {
- value, s.top = s.top.value, s.top.next
- s.size--
- return
- }
- return nil
- }
- func (s *Stack) Top() (value interface{}) {
- return s.top.value
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement