You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

63 lines
1.6 KiB

//
// Lexer.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import Foundation
public enum Token {
case identifier(String, CountableRange<Int>)
case number(Float, CountableRange<Int>)
case parensOpen(CountableRange<Int>)
case parensClose(CountableRange<Int>)
case comma(CountableRange<Int>)
case other(String, CountableRange<Int>)
}
typealias TokenGenerator = (String, CountableRange<Int>) -> Token?
let tokenList: [(String, TokenGenerator)] = [
("[ \t\n]", { _, _ in nil }),
("[a-zA-Z][a-zA-Z0-9]*", { .identifier($0, $1) }),
("\\-?[0-9.]+", { .number(Float($0)!, $1) }),
("\\(", { .parensOpen($1) }),
("\\)", { .parensClose($1) }),
(",", { .comma($1) })
]
public class Lexer {
let input: String
public init(input: String) {
self.input = input
}
public func tokenize() -> [Token] {
var tokens = [Token]()
var content = input
while !content.isEmpty {
var matched = false
for (pattern, generator) in tokenList {
if let (m, r) = content.match(regex: pattern) {
if let t = generator(m, r) {
tokens.append(t)
}
content = String(content[content.index(content.startIndex, offsetBy: m.count)...])
matched = true
break
}
}
if !matched {
let index = content.index(content.startIndex, offsetBy: 1)
let intIndex = content.distance(from: content.startIndex, to: index)
tokens.append(.other(String(content[..<index]), intIndex..<intIndex+1))
content = String(content[index...])
}
}
return tokens
}
}