• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[Swift] Obsługa błędów - mnożenie i dzielenie przed dodawaniem i odejmowaniem

Object Storage Arubacloud
0 głosów
259 wizyt
pytanie zadane 5 marca 2017 w Android, Swift, Symbian przez Piotrinformatyk Początkujący (340 p.)

Witam, 

niestety znowu proszę o pomoc. Uczę się z książki i mam dwa zadania, których do końca nie potrafię zrobić. Zgodnie z tematem, skończyłem czytać zadania o obsłudze błędów. Pierwsze zadanie poszło bardzo szybko (trzeba było dodać odejmowanie). Drugie zadanie jest o dodaniu informacji o tym w jakim indexie wystąpił błąd. W trzecim zadaniu mam dodać mnożenie i dzielenie. To mi się udało ale jest nieprawidłowy wynik. Kiedy próbuję, aby mnożenie i dzielenie miało wyższy priorytet od dodawania i odejmowania to wyskakuje mi, że * jest nieprawidłowym tokenem podczas przetwarzania. Próbowałem zastosować nawiasy, ale nie pykło. W tym momencie chciałem użyć wskazówki w zadaniu o rekurencyjnych  analizatorach składni, ale nie mogę jakoś znaleźć nic co by mi pomogło.

Pewnie kod jest zbyt rozbudowany, ale teraz priorytetem jest, aby najpierw zrozumieć co i jak należy zrobić, aby wszystko działało tak jak należy :)

enum Token {
    case Number(Int)
    case Plus
    case Minus
    case Division
    case Multiplication
}

class Lexer {
    let input: String.CharacterView
    var position: String.CharacterView.Index
    
    enum theError: Error {
        case IncorrectCharacter(Character)
    }
    
    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, "You can not go beyond the data input")
        position = input.index(after: 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(.Multiplication)
                switch nextCharacter {
                case "+":
                    tokens.append(.Plus)
                    advance()
                case "-":
                    tokens.append(.Minus)
                    advance()
                default:
                    advance()
                }
                advance()
            case "/":
                switch nextCharacter {
                case "+":
                    tokens.append(.Plus)
                    advance()
                case "-":
                    tokens.append(.Minus)
                    advance()
                default:
                    advance()
                }
                advance()
            case "+":
                tokens.append(.Plus)
                advance()
            case "-":
                tokens.append(.Minus)
                advance()
            case " ":
                advance()
            default:
                throw theError.IncorrectCharacter(nextCharacter)
            }
        }
        return tokens
    }
}

class Parser {
    let tokens: [Token]
    var position = 0
    
    enum theError: Error {
        case unexpectedEndOfOutput
        case incorrectToken(Token)
    }
    
    init(tokens: [Token]) {
        self.tokens = tokens
    }
    
    func getNextToken() -> Token? {
        guard position < tokens.count else {
            return nil
        }
        let token = tokens[position]
        position += 1
        return token
    }
    
    func getNumber() throws -> Int {
        guard let token = getNextToken() else {
            throw theError.unexpectedEndOfOutput
        }
        switch token {
        case .Number(let value):
            return value
        case .Division:
            throw theError.incorrectToken(token)
        case .Multiplication:
            throw theError.incorrectToken(token)
        case .Plus:
            throw theError.incorrectToken(token)
        case .Minus:
            throw theError.incorrectToken(token)
        }
    }
    func parse() throws -> Int {
        var value = try getNumber()
        
        while let token = getNextToken() {
            switch token {
            case .Multiplication:
                let nextNumber = try getNumber()
                value *= nextNumber
                switch token {
                case .Plus:
                    let nextNumber = try getNumber()
                    value += nextNumber
                case .Minus:
                    let nextNumber = try getNumber()
                    value -= nextNumber
                default:
                    throw theError.incorrectToken(token)
                }
            case .Division:
                let nextNumber = try getNumber()
                value / nextNumber
                switch token {
                case .Plus:
                    let nextNumber = try getNumber()
                    value += nextNumber
                case .Minus:
                    let nextNumber = try getNumber()
                    value -= nextNumber
                default:
                    throw theError.incorrectToken(token)
                }
            case .Plus:
                let nextNumber = try getNumber()
                value += nextNumber
            case .Minus:
                let nextNumber = try getNumber()
                value -= nextNumber
            case .Number:
                throw theError.incorrectToken(token)
            }
        }
        return value
    }
}
func evaluate(input: String) {
    print("Calculation: \(input)")
    
    let lexer = Lexer(input: input)
    do {
        let tokens = try lexer.lex()
        print("Data output lexical analyzer: \(tokens)")
        
        let parser = Parser(tokens: tokens)
        let result = try parser.parse()
        print("Output parser: \(result)")
    }
    catch Lexer.theError.IncorrectCharacter(let character) {
        print("Data output contains invalid character: \(character)")
    }
    catch Parser.theError.unexpectedEndOfOutput {
        print("Unexpected end of data output during processing.")
    }
    catch Parser.theError.incorrectToken(let token) {
        print("Incorrect token during processing: \(token)")
    }
    catch {
        print("Following an unexpected error: \(error).")
    }
}


evaluate(input: "10 + 5 + 3")
evaluate(input: "10 + + 3")
evaluate(input: "10 - 5 + 3")
evaluate(input: "10 * 3 - 3 * 5")

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
0 odpowiedzi 529 wizyt
0 głosów
1 odpowiedź 2,299 wizyt
pytanie zadane 29 sierpnia 2017 w C i C++ przez Mithriandil Początkujący (250 p.)
0 głosów
2 odpowiedzi 242 wizyt
pytanie zadane 25 stycznia 2017 w C i C++ przez Akiro Bywalec (2,910 p.)

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...