Gold challenge

#1

[code]//: Playground - noun: a place where people can play

import Cocoa

enum Token{
case Number(Int)
case Plus
case Min
case Multiply
case Divide
}

class Lexer {
enum Error: ErrorType {
case InvalidCharacter(Character, String.CharacterView.Index)
}
let input: String.CharacterView
var position: String.CharacterView.Index

init(input: String) {
    self.input = input.characters
    self.position = self.input.startIndex
}

func peek() -> Character? {
    guard position < input.endIndex else {
        return nil
    }
    return input[position]
}

func advance() {
    assert(position < input.endIndex, "Cannot advance past the end!")
    ++position
}

func getNumber() -> Int {
    var value = 0
    while let nextCharacter = peek() {
        switch nextCharacter {
            case "0" ... "9":
            let digitValue = Int(String(nextCharacter))!
            value = 10*value + digitValue
            advance()
        default: return value
        }
    }
    return value
}

func lex() throws -> [Token] {
    var tokens = [Token]()
    
    while let nextCharacter = peek() {
        switch nextCharacter {
        case "0" ... "9" : let value = getNumber(); tokens.append(.Number(value))
        case "*" : tokens.append(.Multiply); advance()
        case "/" : tokens.append(.Divide); advance()
        case "+" : tokens.append(.Plus);advance()
        case "-" : tokens.append(.Min);advance()
        case " " : advance()
        default: throw Error.InvalidCharacter(nextCharacter, position)
        }
    }
    return tokens
}

}

func evaluate(input: String) {
print(“Evaluating: (input)”)
let lexer = Lexer(input: input)
do {
let tokens = try lexer.lex()

print("Lexer output: \(tokens)")
    let parser = Parser(tokens: tokens)
    
    // gold solution
    
    try parser.parseMultiplyDivide()

    let result = try parser.parse()
    print("Parser output: \(result)")
    
    
} catch Lexer.Error.InvalidCharacter(let character, let index) {
    print("Input contained an invalid character at index \(index) : \(character)")
} catch Parser.Error.UnexpectedEndOfInput {
    print("Unexpected end of input during parsing")
} catch Parser.Error.InvalidToken(let token, let index) {
    switch token {
    case .Number(let number):
        print("Invalid token during parsing at index \(index): \(number)")
    case .Min, .Plus, .Multiply, .Divide:
        print("Invalid token during parsing at index \(index): \(token)")
    }
} catch { print("An error occurred: \(error)")}

}

class Parser {
enum Error: ErrorType {
case UnexpectedEndOfInput
case InvalidToken(Token, Int)
}

var tokens: [Token]
var position = 0

init(tokens: [Token]) {
    self.tokens = tokens
}

func getNextToken() -> Token? {
    guard position < tokens.count else {
        return nil
    }
    return tokens[position++]
    
}

func getNumber() throws -> Int {
    guard let token = getNextToken() else {
        throw Error.UnexpectedEndOfInput
    }
    switch token {
    case .Number(let value): return value
    case .Plus: throw Error.InvalidToken(token, --position)
    case .Min: throw Error.InvalidToken(token, --position)
    case .Multiply: throw Error.InvalidToken(token, --position)
    case .Divide: throw Error.InvalidToken(token, --position)
    }
}

// gold solution

func parseMultiplyDivide() throws  {
    position = tokens.startIndex
    while let token = getNextToken() {
        switch token {
        case  .Multiply :
                if position > 1 {position -= 2; var value = try getNumber();position++
                let nextNumber = try getNumber()
                value *= nextNumber
                position--;tokens.removeAtIndex(position)
                position--;tokens.removeAtIndex(position)
                position--
                tokens[position] = .Number(value);}
        case  .Divide :
                if position > 1 { position -= 2; var value = try getNumber();position++
                let nextNumber = try getNumber()
                value /= nextNumber
                position--;tokens.removeAtIndex(position)
                position--;tokens.removeAtIndex(position)
                position--
                tokens[position] = .Number(value);}
        default: break
        }
    }
 
    return
}

func parse() throws -> Int {
    position = tokens.startIndex
    var value = try getNumber()
    
    while let token = getNextToken() {
        switch token {
        case  .Plus : let nextNumber = try getNumber()
            value += nextNumber
        case .Min : let nextNumber = try getNumber()
            value -= nextNumber
        case.Multiply : throw Error.InvalidToken(token, --position)
        case.Divide : throw Error.InvalidToken(token, --position)
        case .Number: throw Error.InvalidToken(token, --position)
        }
    }
    return value
}

}

evaluate(" 5 * 3 - 20 / 4 ")
[/code]