编辑代码

import Foundation

enum Token {
    case number(Double)
    case operatorToken(OperatorType)
    case leftParenthesis
    case rightParenthesis
    case none
}

enum OperatorType: Character {
    case addition = "+"
    case subtraction = "-"
    case multiplication = "*"
    case division = "/"
    case exponentiation = "^"
    case modulus = "%"
}

class Calculator {
    var tokens: [Token] = []
    var index = 0

    func parseInput(_ input: String) {
        var currentNumberString = ""

        for character in input {
            switch character {
            case "0"..."9", ".":
                currentNumberString.append(character)
            case "+", "-", "*", "/", "^", "%":
                addNumberToken(&currentNumberString)
                tokens.append(.operatorToken(OperatorType(rawValue: character)!))
            case "(":
                addNumberToken(&currentNumberString)
                tokens.append(.leftParenthesis)
            case ")":
                addNumberToken(&currentNumberString)
                tokens.append(.rightParenthesis)
            default:
                break
            }
        }

        addNumberToken(&currentNumberString)
    }

    func addNumberToken(_ numberString: inout String) {
        if let number = Double(numberString) {
            tokens.append(.number(number))
        }
        numberString = ""
    }
    func calculate() -> Double {
        guard !tokens.isEmpty else { return 0.0 }
        return evaluateExpression()
    }
    func evaluateExpression() -> Double {
        var value = evaluateTerm()
        while index < tokens.count, case let .operatorToken(op) = tokens[index] {
            if op == .addition || op == .subtraction {
                index += 1
                let termValue = evaluateTerm()
                value = (op == .addition) ? value + termValue : value - termValue
            } else {
                break
            }
        }
        return value
    }
    func evaluateTerm() -> Double {
        var value = evaluateFactor()
        while index < tokens.count, case let .operatorToken(op) = tokens[index] {
            if op == .multiplication || op == .division || op == .exponentiation || op == .modulus {
                index += 1
                let factorValue = evaluateFactor()

                switch op {
                case .multiplication:
                    value *= factorValue
                case .division:
                    if factorValue != 0 {
                        value /= factorValue
                    } else {
                        fatalError("Division by zero error!")
                    }
                case .exponentiation:
                    value = pow(value, factorValue)
                case .modulus:
                    if factorValue != 0 {
                        value = value.truncatingRemainder(dividingBy: factorValue)
                    } else {
                        fatalError("Modulus by zero error!")
                    }
                default:
                    break
                }
            } else {
                break
            }
        }
        return value
    }
    func evaluateFactor() -> Double {
        if index < tokens.count {
            switch tokens[index] {
            case .number(let value):
                index += 1
                return value
            case .leftParenthesis:
                index += 1
                let value = evaluateExpression()
                guard index < tokens.count, case .rightParenthesis = tokens[index] else {
                    fatalError("Mismatched parentheses!")
                }
                index += 1
                return value
            default:
                break
            }
        }
        fatalError("Invalid expression!")
    }
}
print("Swift Calculator Start!")
print("Enter some expressions (type 'exit' to quit): ")

var calculator = Calculator()
while true {
    print(">>> ", terminator: "")
    if let input = readLine(), input.lowercased() != "exit" {
        calculator = Calculator()
        calculator.parseInput(input)
        let result = calculator.calculate()
        print("Result: \(result)")
    } else {
        break
    }
}