Silver Challenge (simple solution)


#1

import Cocoa
import Foundation

enum Token {
case Number(int: Int, index: String.CharacterView.Index)
case Plus(String.CharacterView.Index) // my modification for the Silver Challenge
case Minus(String.CharacterView.Index) // my modification for the Silver Challenge

func index() -> String.CharacterView.Index {        // my add to the Silver Challenge
    switch self {
    case let Plus(index):
        return index
    case let Minus(index):
        return index
    case let Number(int: _, index: index):
        return index
    }
}

func stringa() -> String {                          // my add to the Silver Challenge
    switch self {
    case let Number(int: int, index: _):
        return String(int)
    case Plus(_):
        return "+"
    case Minus(_):
        return "-"
    }
}

}

class Lexer {
enum Error: ErrorType {
case invalidCharacter(Character)
}
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 = position.successor() // instead of the deprecated: "++position"
}

func lex() throws -> [Token] {
    var tokens = [Token]()
    
    while let nextCharacter = peek() {
        switch nextCharacter {
        case "0" ... "9":
            let value = getNumber()
            tokens.append(.Number(int: value, index: position.predecessor()))// my modification for the Silver Challenge
        case "+":
            tokens.append(.Plus(position))// my modification for the Silver Challenge
            advance()
        case "-":
            tokens.append(.Minus(position))     // my modification for the Silver Challenge
            advance()
        case " ":
            advance()
        default:
            throw Error.invalidCharacter(nextCharacter)
        }
    }
    return tokens
}
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 evaluate(input: String) {
print(“Evaluating: (input)”)
let lexer = Lexer(input: input)
do {
let tokens = try lexer.lex()
let parser = Parser(tokens: tokens)
let result = try parser.parse()
print(“Parser output: (result)”)
}
catch Lexer.Error.invalidCharacter(let character) {
let index = input.lowercaseString.characters.indexOf(character) // my add for the Silver Challenge
print(“Input contained an invalid character at index (index!): (character)”) // my modification for the Silver Challenge
}
catch Parser.Error.UnexpectedEndOfInput {
print(“Unexpected end of input during parsing”)
}
catch Parser.Error.InvalidToken(let token) {
print(“Invalid token during parsing at index (token.index()): (token.stringa())”) // my modification for the Silver Challenge
}
catch {
print(“An error occured: (error)”)
}
}

class Parser {
enum Error: ErrorType {
case UnexpectedEndOfInput
case InvalidToken(Token)
}
let 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, _): // my modification for the Silver Challenge
        return value
    case .Plus:
        throw Error.InvalidToken(token)
    case .Minus:
        throw Error.InvalidToken(token)                               
    }
}
func parse() throws -> Int {
    var value = try getNumber()
    
    while let token = getNextToken() {
        switch token {
        case .Plus:
            let nextNumber = try getNumber()
            value += nextNumber
        case .Minus:
            let nextNumber = try getNumber()                           
            value -= nextNumber
        case .Number:
            throw Error.InvalidToken(token)
        }
    }
    return value
}

}

evaluate(“10 + 3 3 - 5”)

evaluate(“10 + 3 5”)
evaluate(“10 +”)
evaluate(“1 + 2 + abcdefg”)
evaluate(“10 - 2 - 3”)
evaluate(“1 + 3 + 7a + 8”)
evaluate(“10 + 3 3 + 7”)


Silver Challenge
Silver Challenge
Silver Challenge
Silver Challenge