Skip to content

Instantly share code, notes, and snippets.

@zonble
Created August 5, 2019 15:53

Revisions

  1. zonble created this gist Aug 5, 2019.
    78 changes: 78 additions & 0 deletions calc.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    enum Token {
    case num(Int)
    case op(String)
    }

    func tokenize(_ s: String) -> [Token] {
    let scanner = Scanner(string: s)
    scanner.charactersToBeSkipped = CharacterSet.whitespaces
    var tokens = [Token]()
    while !scanner.isAtEnd {
    if let c = scanner.scanCharacters(from: CharacterSet(charactersIn: "+-*/")) {
    tokens.append(.op(String(c)))
    }
    else if let int = scanner.scanInt() {
    tokens.append(.num(int))
    }
    }
    return tokens
    }

    enum MyError : Error {
    case invalidToken
    }

    func calc(_ tokens: [Token]) throws -> Int {
    if tokens.count == 0 {
    return 0
    }
    guard case let .num(x) = tokens[0] else {
    throw MyError.invalidToken
    }
    var v = x
    var currentToken: Token = tokens[0]
    for token in tokens[1...] {
    switch token {
    case .num(let i):
    switch currentToken {
    case .num(_):
    throw MyError.invalidToken
    case .op(let c):
    switch c {
    case "+":
    v += i
    case "-":
    v -= i
    case "*":
    v *= i
    case "/":
    v /= i
    default:
    throw MyError.invalidToken
    }
    currentToken = token
    }
    case .op(_):
    switch currentToken {
    case .op(_):
    throw MyError.invalidToken
    case .num(_):
    currentToken = token
    }
    break
    }
    }
    return v
    }

    //let t = tokenize("1 / 1 * 2 + 100 - 80")
    let t = tokenize("1 + 100 * 200")

    print(t)
    t
    do {
    let result = try calc(t)
    result
    } catch {
    error
    }