 import Foundation
 
 internal protocol Token {
-    func match(_ string: String, matchRange: NSRange) -> NSRange
+    func match(_ string: String, matchRange: Range<String.Index>) -> Range<String.Index>?
     func isNewLine() -> Bool
 }
 

    
    var line = 0
    var column = 0

    // FIXME: This is temporary until the the following known issue is fixed. https://github.com/apple/swift-corelibs-foundation/blob/master/Docs/Issues.md#known-issues
#if os(Linux) || os(FreeBSD)
    var matchString: String { get { return stringStream.bridge().substring(with: matchRange) } }
#else
    var matchString: String { get { return (stringStream as NSString).substring(with: matchRange) } }
#endif
    
    fileprivate var stringStream: String
    fileprivate var matchRange: NSRange
    
    init(string: String) {
        self.stringStream = string
        self.matchRange = NSMakeRange(0, string.characters.count)
        
        if self.stringStream.characters.count > 0 {
            line = 1

    }
    
    func accept(_ token: T) -> String? {
        if let range = token.match(stringStream, matchRange: matchRange) {
            
            if token.isNewLine() {
                line += 1
                column = 1
            } else {
                column += stringStream.distance(from: range.lowerBound, to: range.upperBound)
            }
            // Increment the range for matching
            matchRange = range.upperBound..<matchRange.upperBound
            
            return stringStream.substring(with: range)
        }
        return nil
    }
    
    func expect(_ token: T) -> Bool {
        return token.match(stringStream, matchRange: matchRange) != nil
    }
    
    var matchString: String {
        get {
            return stringStream.substring(with: matchRange)
        }
    }
}
