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")