• 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

VPS Starter Arubacloud
0 głosów
279 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 751 wizyt
0 głosów
1 odpowiedź 2,405 wizyt
pytanie zadane 29 sierpnia 2017 w C i C++ przez Mithriandil Początkujący (250 p.)
0 głosów
2 odpowiedzi 266 wizyt
pytanie zadane 25 stycznia 2017 w C i C++ przez Akiro Bywalec (2,910 p.)

93,004 zapytań

141,969 odpowiedzi

321,248 komentarzy

62,340 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

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...