Solved: I was missing the advance()
on line 60
I thought I should add my process to figured this out, otherwise it would be a somewhat pointless post. I retyped the whole code from the chapter up to that point out in a new playground file , and it worked. So to figure out what I got wrong the first time I went to Xcode->Developer Tools->File Merge and did a comparison of the two files.
On p.276 it says the output should be:
Evaluating: 10 + 3 + 5
Lexer output: [ Token.number(10), Token.plus, Token.number(3), Token.plus, Token.number(5)]
Evaluating: 1 + 2 +abcdefg
An error occurred: Lexer.Error.invalidCharacter(“a”)
However my output is just:
Evaluating: 10 + 3 + 5
It looks like my do/catch is not executing. What’s going on?
Code:
import Cocoa
enum Token {
case number(Int)
case plus
}
class Lexer {
enum Error: Swift.Error {
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 endIndex!")
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(.plus)
case " ":
advance()
default:
throw Lexer.Error.invalidCharacter(nextCharacter)
}
}
return tokens
}
}
func evaluate(_ input: String) {
print("Evaluating: \(input)")
let lexer = Lexer(input: input)
do {
let tokens = try lexer.lex()
print("Lexer output: \(tokens)")
} catch {
print("An error occurred: \(error)")
}
}
evaluate("10 + 3 + 5")
evaluate("1 + 2 + abcdefg")