Gold chanllenge

#1

add term() to the original code to handle * and / operation

enum Token{
    case Number(Int)
    case Op(Character)
}

class Lexer{
    
    enum Error:ErrorType{
        case InvalidCharacter(String.CharacterView.Index,Character)
    }
    
    var input: String.CharacterView//string.characters
    var position: String.CharacterView.Index// charaters.startIndex or endIndex
    
    init(input:String){
        self.input = input.characters
        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 = position.successor()
    }
    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(.Op("+"))
                advance()
                case "-":
                tokens.append(.Op("-"))
                advance()
                case "*":
                tokens.append(.Op("*"))
                advance()
               case "/":
                tokens.append(.Op("/"))
                advance()
                
                case " ":
                advance()
                default: throw Error.InvalidCharacter(position,nextCharacter)
            }
        }
        return tokens
    }
}

class Parser{
    enum Error:ErrorType{
        case UnexpectedEndOfInput
        case InvalidToken(Int,Token)
        case CannotDivideToZero(Token)
    }
    
    let tokens: [Token]
    var position = 0
    init(tokens:[Token]){ self.tokens = tokens }
    
    func getNextToken()->Token?
    {
        guard position < tokens.count else { return nil }
        let currentPosition = position
        position += 1
        return tokens[currentPosition]
    }
    
    func getNumber()throws->Int{
        guard let token = getNextToken() else { throw Error.UnexpectedEndOfInput}
        switch token{
            case .Number(let value):
            return value
            default:
            throw Error.InvalidToken(position,token)
        }
    
    }
   
    func term()throws->Int{
             var value = try getNumber()
             while let token = getNextToken(){
                 switch token{
            case .Op("*"):
            let nextValue = try getNumber()
            value *= nextValue
          
           case .Op("/"):
             let nextValue = try getNumber()
             guard nextValue > 0 else { 
             throw Error.CannotDivideToZero(token)}          
             value = value / nextValue
             
             default:
             position -= 1
             return value
            
                 }
             }
             return value
    }
   
    func parse()throws->Int{
        var value = try term()
        while let token = getNextToken(){
            switch token{
            case .Op("+"):
            let nextValue = try term()
            value += nextValue
            
            case .Op("-"):
            let nextValue = try term()
            value -= nextValue
            
            default:
            throw Error.InvalidToken(position,token)
        }
       }
       return value
    }
}

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)
        let result = try parser.parse()
        print("Parser output: \(result)")
    }catch Lexer.Error.InvalidCharacter(let a,let char){
        print("Input contained a invalided character at index \(a) : \(char)")}catch Parser.Error.UnexpectedEndOfInput
        { print("unexpected end of input during parsing")
    }catch Parser.Error.InvalidToken(let a,let token) {print("Invalid token during parsing at \(a): \(token)")}
    catch Parser.Error.CannotDivideToZero(let token){
        print("Cannot divide to 0 \(token)")
    } catch{"An error occurred: \(error)"
}
}

evaluate("10+3+2+2*5+3")
evaluate("10+3*5*3")
evaluate("10-9/3*2")

Evaluating: 10+3+2+2*5+3
Lexer output: [main.Token.Number(10), main.Token.Op("+"), main.Token.Number(3), main.Token.Op("+"), main.Token.Number(2), main.Token.Op("+"), main.Token.Number(2), main.Token.Op("*"), main.Token.Number(5), main.Token.Op("+"), main.Token.Number(3)]
Parser output: 28
Evaluating: 10+3*5*3
Lexer output: [main.Token.Number(10), main.Token.Op("+"), main.Token.Number(3), main.Token.Op("*"), main.Token.Number(5), main.Token.Op("*"), main.Token.Number(3)]
Parser output: 55
Evaluating: 10-9/3*2
Lexer output: [main.Token.Number(10), main.Token.Op("-"), main.Token.Number(9), main.Token.Op("/"), main.Token.Number(3), main.Token.Op("*"), main.Token.Number(2)]
Parser output: 4
#2

add “(” expression “)” function, but it’s no good that has a serious bug if miss one “(”

enum Token{
    case Number(Int)
    case Op(Character)
    
}

class Lexer{
    
    enum Error:ErrorType{
        case InvalidCharacter(String.CharacterView.Index,Character)
    }
    
    var input: String.CharacterView//string.characters
    var position: String.CharacterView.Index// charaters.startIndex or endIndex
    
    init(input:String){
        self.input = input.characters
        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 = position.successor()
    }
    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(.Op("+"))
                advance()
                case "-":
                tokens.append(.Op("-"))
                advance()
                case "*":
                tokens.append(.Op("*"))
                advance()
                case "/":
                tokens.append(.Op("/"))
                advance()
                case "(":
                tokens.append(.Op("("))
                advance()
                case ")":
                tokens.append(.Op(")"))
                advance()
                
                case " ":
                advance()
                default: throw Error.InvalidCharacter(position,nextCharacter)
            }
        }
        return tokens
    }
}




class Parser{
    enum Error:ErrorType{
        case UnexpectedEndOfInput
        case InvalidToken(Int,Token)
        case CannotDivideToZero(Token)
    
    }
    
    let tokens: [Token]
    var position = 0
    init(tokens:[Token]){ self.tokens = tokens }
    
    func getNextToken()->Token?
    {
        guard position < tokens.count else { return nil }
        let currentPosition = position
        position += 1
        return tokens[currentPosition]
    }
    
    func getNumber()throws->Int{
        guard let token = getNextToken() else { throw Error.UnexpectedEndOfInput}
        switch token{
            case .Op("("):
                          let value =  try parse()
 guard let parentheseToken = getNextToken() else { throw Error.UnexpectedEndOfInput}
           if case let Token.Op(ch) = parentheseToken where ch == ")" {return value}else{throw Error.UnexpectedEndOfInput}
                        
                          
            case .Number(let value):
            return value
            default:
           
            throw Error.InvalidToken(position,token)
        }
    
    }
   
    func term()throws->Int{
             var value = try getNumber()
             while let token = getNextToken(){
                 switch token{
            case .Op("*"):
            let nextValue = try getNumber()
            value *= nextValue
          
           case .Op("/"):
             let nextValue = try getNumber()
             guard nextValue > 0 else { 
             throw Error.CannotDivideToZero(token)}          
             value = value / nextValue
             
             default:
             position -= 1
             return value
            
                 }
             }
             return value
        
    }
   
    
    func parse()throws->Int{
        var value = try term()
        while let token = getNextToken(){
            switch token{
            case .Op("+"):
            let nextValue = try term()
            value += nextValue
            
            case .Op("-"):
            let nextValue = try term()
            value -= nextValue
            
            default:
            position -= 1
            return value
        }
        
       }
       return value
    }
}

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)
        let result = try parser.parse()
        print("Parser output: \(result)")
    }catch Lexer.Error.InvalidCharacter(let a,let char){
        print("Input contained a invalided character at index \(a) : \(char)")}catch Parser.Error.UnexpectedEndOfInput
        { print("unexpected end of input during parsing")
    }catch Parser.Error.InvalidToken(let a,let token) {print("Invalid token during parsing at \(a): \(token)")}
    catch Parser.Error.CannotDivideToZero(let token){
        print("Cannot divide to 0 \(token)")
    }catch{"An error occurred: \(error)"}
}

evaluate("20-2*(5+3+4)+80 / (4+4)")
evaluate("(10+(3*(5+3+4)+4))/5")

Evaluating: 20-2*(5+3+4)+80 / (4+4)
Lexer output: [main.Token.Number(20), main.Token.Op("-"), main.Token.Number(2), main.Token.Op("*"), main.Token.Op("("), main.Token.Number(5), main.Token.Op("+"), main.Token.Number(3), main.Token.Op("+"), main.Token.Number(4), main.Token.Op(")"), main.Token.Op("+"), main.Token.Number(80), main.Token.Op("/"), main.Token.Op("("), main.Token.Number(4), main.Token.Op("+"), main.Token.Number(4), main.Token.Op(")")]
Parser output: 6
Evaluating: (10+(3*(5+3+4)+4))/5
Lexer output: [main.Token.Op("("), main.Token.Number(10), main.Token.Op("+"), main.Token.Op("("), main.Token.Number(3), main.Token.Op("*"), main.Token.Op("("), main.Token.Number(5), main.Token.Op("+"), main.Token.Number(3), main.Token.Op("+"), main.Token.Number(4), main.Token.Op(")"), main.Token.Op("+"), main.Token.Number(4), main.Token.Op(")"), main.Token.Op(")"), main.Token.Op("/"), main.Token.Number(5)]
Parser output: 10