Here's the code:
import Cocoa
protocol ExprNode: CustomStringConvertible {
}
enum Token {
case number(Int)
case plus
case minus
case multiply
case divide
}
struct TokenStruct {
var token: Token
var position: Int
}
class Lexer {
enum Error: Swift.Error {
case invalidCharacter(Character, pos: Int)
}
let input: String.CharacterView
var position: String.CharacterView.Index
var indexes = [Int]()
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 -> [TokenStruct] {
var tokens = [TokenStruct]()
while let nextCharacter = peek() {
switch nextCharacter {
case "0"..."9":
let posChar = input.distance(from: input.startIndex, to: position)
let value = getNumber()
tokens.append(TokenStruct(token: .number(value), position: posChar))
case "+":
let posChar = input.distance(from: input.startIndex, to: position)
tokens.append(TokenStruct(token: .plus, position: posChar))
advance()
case "-":
let posChar = input.distance(from: input.startIndex, to: position)
tokens.append(TokenStruct(token: .minus, position: posChar))
advance()
case "*":
let posChar = input.distance(from: input.startIndex, to: position)
tokens.append(TokenStruct(token: .multiply, position: posChar))
advance()
case "/":
let posChar = input.distance(from: input.startIndex, to: position)
tokens.append(TokenStruct(token: .divide, position: posChar))
advance()
case " ":
/
advance()
default:
let distanceToPosition = input.distance(from: input.startIndex, to: position)
throw Lexer.Error.invalidCharacter(nextCharacter, pos: distanceToPosition)
}
}
return tokens
}
}
class Parser {
enum Error: Swift.Error {
case unexpectedEndOfInput
case invalidToken(TokenStruct)
}
/
let tokens: [TokenStruct]
var position = 0
init(tokens: [TokenStruct]) {
self.tokens = tokens
}
func getNextToken() -> TokenStruct? {
guard position < tokens.count else {
return nil
}
func getNumber() throws -> Int {
guard let token = getNextToken() else {
throw Parser.Error.unexpectedEndOfInput
}
switch token.token {
case .number(let value):
return value
case .plus, .minus, .multiply, .divide:
throw Parser.Error.invalidToken(token)
}
}
func peekNextToken() -> TokenStruct?
{
guard position < tokens.count else
{
return nil
}
let token = tokens[position]
return token
}
func parse() throws -> Int
{
var value = try parseMultiplyDivide()
while let token = getNextToken()
{
switch token.token
{
case .plus:
let nextNumber = try parseMultiplyDivide()
value += nextNumber
case .minus:
let nextNumber = try parseMultiplyDivide()
value -= nextNumber
case .multiply, .divide, .number:
throw Parser.Error.invalidToken(token)
}
}
return value
}
func parseMultiplyDivide() throws -> Int
{
/
var value = try getNumber()
while let token = peekNextToken()
{
switch token.token
{
case .plus, .minus:
return value
case .multiply:
getNextToken()
let nextNumber = try getNumber()
value *= nextNumber
case .divide:
getNextToken()
let nextNumber = try getNumber()
value /= nextNumber
case .number:
throw Parser.Error.invalidToken(token)
}
}
return value
}
}
}
func evaluate(_ input: String) {
print("Evaluating: \(input)")
let lexer = Lexer(input: input)
do {
let tokens = try lexer.lex()
print("Lexer output: \(tokens)")
let parser = Parser(tokens: tokens)
let result = try Parser.parse()
print("Parser output: \(result)")
} catch Lexer.Error.invalidCharacter(let character, let posErr) {
print("Input contained an invalid character at index \(posErr): \(character)")
} catch Parser.Error.unexpectedEndOfInput {
print("Unexpected end of input during parsing")
} catch Parser.Error.invalidToken(let token) {
print("Invalid token \(token.token) during parsing at index: \(token.position)")
} catch {
print("An error occured: \(error)")
}
}
evaluate("10 * 3 + 5 * 3")
and I get the error:
Type 'Parser' has no member 'parse' in line 191
The function 'parse' is clearly above the evaluation. I don't understand??