Witam :) Pisałem wcześniej, ale nikt nie odpowiedział: https://forum.pasja-informatyki.pl/232719/swift-obsluga-bledow-mnozenie-i-dzielenie-przed-dodawaniem-i-odejmowaniem?show=232719#q232719
Zmieniłem kod na tyle, że myślę, że lepiej będzie jak nowe pytanie zadam. Gdyby nie jeden błąd to pewnie bym nie napisał, ale nie rozumiem skąd on wynika:
Błąd: Expected declaration. Jak rozwinę to mi pisze: In declaration of 'Parser'. Znajduje się on przy wywoływaniu funkcji na samym dole.
Uczę się z książki i mam dodać odejmowanie (zrobiłem bardzo szybko), mnożenie i dzielenie (połowicznie bo nie uwzględnia pierwszeństwa co próbuję zrobić) i dodanie index-u do komunikatu błędu(tak średnio wiem co mam zrobić).
Ktoś pomoże mi zrozumieć co źle robię? Najlepiej też z tym indexem jakby mi ktoś pomógł
enum Token {
//rodzaje tokenów
case Number(Int)
case Plus
case Minus
case Division
case Multiplication
case OpeningBracket
case ClosingBracket
}
//analizator leksykalny - budowa
class Lexer {
//String.CharacterView ma właściwości startIndex i endIndex
let input: String.CharacterView
var position: String.CharacterView.Index
enum theError: Error { //zgłasza błąd
case IncorrectCharacter(Character)
}
init(input: String) {
self.input = input.characters //inicjalizujemy właściwośc wraz z danymi wejściowymi,ma wartość wskazującą początek tych danych wejściowych
self.position = self.input.startIndex
}
//może być wywołana zawsze
func peek() -> Character? { //spradzenie kolejnego znaku w danych wejściowych. Wskazuje analizatorowi, że zostały przetworzone wszystkie dane wejściowe
guard position < input.endIndex else {
return nil
}
return input[position]
}
//IMPLEMENTACJA ALGORYTMU ANALIZATORA
//można wywołać tylko wtedy, gdy aktualne położenie nie jest końcem danych wejściowych
func advance() { //przejście do kolejnego znaku
assert(position < input.endIndex, "You can not go beyond the data input") //gdy false - wpadnięcie w pułapkę i wyświetlenie komunikatu
position = input.index(after: position)
}
func getNumber () -> Int { //wyodrębnia liczby całkowite z danych wejściowych
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] { //throws, czyli funkcja/metoda może wygenerować błąd
var tokens = [Token]() //tablica z tokenami
while let nextCharacter = peek() { //przetworzenie wszystkich danych wejściowych
switch nextCharacter {
case "(":
tokens.append(.OpeningBracket)
advance()
case ")":
tokens.append(.ClosingBracket)
case "0"..."9":
let value = getNumber()
tokens.append(.Number(value))
case "*":
tokens.append(.Multiplication)
advance()
case "/":
tokens.append(.Multiplication)
advance()
case "+":
tokens.append(.Plus)
advance()
case "-":
tokens.append(.Minus)
advance()
case " ":
advance()
default:
throw theError.IncorrectCharacter(nextCharacter) //throws zatrzymuje funkcje i przekazuje błąd do komponentu wywołąjącego dany błąd zgodnego z protokołem Error
}
}
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? { //peek() i advance() w jedną
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)
case .OpeningBracket:
throw theError.incorrectToken(token)
case .ClosingBracket:
throw theError.incorrectToken(token)
}
}
func parse() throws -> Int {
var value = try getNumber()
while let token = getNextToken() {
switch token {
case .OpeningBracket:
try getBrackets()
case .ClosingBracket:
try getNumber()
case .Multiplication:
let nextNumber = try getNumber()
value *= nextNumber
case .Division:
let nextNumber = try getNumber()
value / nextNumber
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 getBrackets() throws {
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
}
}
}
func evaluate(input: String) {
print("Calculation: \(input)")
let lexer = Lexer(input: input)
do {
//wprowadza nowy zasięg, jeżeli jakieś wywołanie try spowoduje zgłoszenie błędu nastąpi wykonanie odpowiedniego bloku catch
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) { //zgłoszona wartość błędu jest przypisywana stłej error
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)")