Fundamentals 13 min read

Converting Infix Expressions to Postfix and Evaluating Them in Swift

This article explains how to transform a typical infix arithmetic expression such as "8 - (6 + 4 / 2 - 1) * 2" into a postfix (Reverse Polish) form using Swift, then evaluates the postfix expression step by step with custom Swift functions and also shows a shortcut using NSExpression.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Converting Infix Expressions to Postfix and Evaluating Them in Swift

Background : While developing a "24‑point challenge" app the author needed to compute the result of arbitrary arithmetic strings like 8 - (6 + 4 / 2 - 1) * 2 and show the whole calculation process.

Infix vs. Postfix : An infix expression places operators between operands, which is natural for humans but difficult for computers. Converting it to postfix (Reverse Polish) puts the operator after its operands, making evaluation straightforward.

Conversion algorithm : The algorithm uses two arrays to simulate a stack (one for numbers, one for operators). It scans the expression from left to right, handling parentheses, operator precedence, and finally outputs the postfix array.

Swift implementation – conversion :

func converExpressionToSuffixExpression(_ expressionStr: String) -> [String] {
    var suffixExpressionList: [String] = []
    var operatorExpressionList: [String] = []
    for item in expressionStr {
        let itemStr = String(item)
        if itemStr == " " { continue }
        if item.isNumber {
            suffixExpressionList.append(itemStr)
        } else {
            if operatorExpressionList.isEmpty {
                operatorExpressionList.append(itemStr)
            } else {
                if itemStr == ")" {
                    let temp = handleAppendExpressionList(operatorExpressionList, suffixList: suffixExpressionList, isRightBracket: true)
                    operatorExpressionList = temp.l1
                    suffixExpressionList = temp.l2
                } else {
                    let lastStr = operatorExpressionList.last!
                    let isItemPriorityHigh = isFirstOperatorPriorityHigh(first: itemStr, second: lastStr)
                    if isItemPriorityHigh || itemStr == "(" || lastStr == "(" {
                        operatorExpressionList.append(itemStr)
                    } else {
                        let temp = handleAppendExpressionList(operatorExpressionList, suffixList: suffixExpressionList, isRightBracket: false)
                        operatorExpressionList = temp.l1
                        suffixExpressionList = temp.l2
                        operatorExpressionList.append(itemStr)
                    }
                }
            }
        }
    }
    while !operatorExpressionList.isEmpty {
        if let last = operatorExpressionList.popLast() {
            suffixExpressionList.append(last)
        }
    }
    return suffixExpressionList
}

func handleAppendExpressionList(_ operatorList: [String], suffixList: [String], isRightBracket: Bool) -> ([String], [String]) {
    var operatorExpressionList = operatorList
    var suffixExpressionList = suffixList
    var lastStr = operatorExpressionList.last
    repeat {
        guard let tempLastStr = operatorExpressionList.popLast() else { break }
        lastStr = tempLastStr
        if tempLastStr != "(" {
            suffixExpressionList.append(tempLastStr)
        } else if isRightBracket {
            operatorExpressionList.append("(")
        }
    } while lastStr != "(" && lastStr != ""
    return (operatorExpressionList, suffixExpressionList)
}

func isFirstOperatorPriorityHigh(first: String, second: String) -> Bool {
    let isFirst = isMultiplyOrDivideOperator(itemStr: first)
    let isSecond = isMultiplyOrDivideOperator(itemStr: second)
    return isFirst && !isSecond
}

func isMultiplyOrDivideOperator(itemStr: String) -> Bool {
    return ["*", "x", "×", "X", "/", "÷"].contains(itemStr)
}

Postfix evaluation principle : Scan the postfix array from left to right; when an operator is encountered, take the two preceding numbers, compute a op b, replace the three elements with the result, and continue until a single element remains.

Swift implementation – evaluation :

func calculatorExpressionList(_ expressionList: [String]) -> Double {
    if expressionList.count == 1 {
        return (expressionList.first as NSString?)?.doubleValue ?? 0.0
    }
    var targetList = expressionList
    for (index, item) in expressionList.enumerated() {
        if isOperator(item) {
            let a = expressionList[index - 2]
            let b = expressionList[index - 1]
            let r = calculator(a, item, b)
            targetList[index - 2] = r
            targetList.removeSubrange(Range(NSRange(location: index - 1, length: 2))!)
            break
        }
    }
    return calculatorExpressionList(targetList)
}

func calculator(_ a: String, _ op: String, _ b: String) -> String {
    let aValue = (a as NSString).doubleValue
    let bValue = (b as NSString).doubleValue
    var result: Double = 0.0
    switch op {
    case "+": result = aValue + bValue
    case "-": result = aValue - bValue
    case "*", "×", "x", "X": result = aValue * bValue
    case "/", "÷": if bValue != 0 { result = aValue / bValue }
    default: break
    }
    return String(format: "%f", result)
}

func isOperator(_ str: String) -> Bool {
    if isMultiplyOrDivideOperator(itemStr: str) { return true }
    return str == "+" || str == "-"
}

Shortcut with NSExpression : For simple calculations the built‑in NSExpression class can evaluate a formatted string directly.

let expressionStr = "2 + 3 * (5 - 1)"
let formatted = expressionStr.replacingOccurrences(of: " ", with: "")
let expression = NSExpression(format: formatted)
if let result = expression.expressionValue(with: nil, context: nil) as? NSNumber {
    print(result)
}

Summary : The article provides a complete Swift solution for converting infix arithmetic strings to postfix notation, evaluating the postfix expression, and an alternative using NSExpression. The full source code is available at GitHub .

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

iOSSwiftExpression EvaluationInfix to Postfix
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.