 //MARK:- Description
 
 extension JSONPath: CustomDebugStringConvertible {
-
+    
     public var debugDescription: String {
         var description = ""
-
+        
         for component in components {
             switch component {
             case .Text(let text):
                 description += "['\(text)']"
                 break
-
+                
             case .Numeric(let number):
                 description += "[\(number)]"
-
+                
             case .SelfReference:
                 description += "[self]"
             }
         }
-
+        
         return description
     }
 }
 
 
-//MARK: NSScanner parsing extension
-
-extension NSScanner {
-
-
-    private static let dotCharacterSet = NSCharacterSet(charactersInString: ".")
-
-    private func consumeOptionalTraillingDot() {
-        scanCharactersFromSet(NSScanner.dotCharacterSet, intoString: nil)
-    }
-
-
-    private static let singleQuoteDelimittedStringDelimiters = NSCharacterSet(charactersInString:"`'")
-
-    private func scanSingleQuoteDelimittedString(inout string: String) throws -> Bool {
-
-        guard scanString("'", intoString: nil) else {
-            return false
-        }
-
-        var text = ""
-        mainLoop: while !atEnd {
-            //Scan normal text
-            var fragment: NSString?
-            let didScanFragment = scanUpToCharactersFromSet(NSScanner.singleQuoteDelimittedStringDelimiters, intoString:&fragment)
-            if didScanFragment,
-                let fragment = fragment as? String {
-                    text.appendContentsOf(fragment)
-            }
-
-            //Scan escape sequences
-            escapeSequenceLoop: while true {
-                if scanString("`'", intoString: nil) {
-                    text.appendContentsOf("'")
-                } else
-                    if scanString("``", intoString: nil) {
-                        text.appendContentsOf("`")
-                    } else
-                        if scanString("`", intoString: nil) {
-                            text.appendContentsOf("`") //This is technically an invalid escape sequence but we're forgiving.
-                        } else {
-                            break escapeSequenceLoop
-                }
-            }
-
-            //Attempt to scan the closing delimiter
-            if scanString("'", intoString: nil) {
-                //Done!
-                string = text
-                return true
-            }
-        }
-        
-        throw JSONPath.ParsingError.UnexpectedEndOfString
-    }
-}
+//MARK:- String encoding
+
+extension JSONPath {
+
+    /**
+    <#Description#>
+
+    - parameter text: <#text description#>
+
+    - returns: <#return value description#>
+    */
+    public static func encodeTextAsSubscriptPathComponent(text: String) -> String {
+        let mutableText =  NSMutableString(string: text)
+        //Note that the order of the replacements is significant. We must replace '`' first otherwise our replacements will get replaced.
+        mutableText.replaceOccurrencesOfString("`", withString: "``", options: [], range: NSRange(location: 0, length: mutableText.length))
+        mutableText.replaceOccurrencesOfString("'", withString: "`'", options: [], range: NSRange(location: 0, length: mutableText.length))
+
+        return "['\(mutableText)']"
+    }
+}

        case (_) where scanner.scanString("self", intoString: nil):
            result = .SelfReference

        case (_) where try scanner.scanSingleQuoteDelimittedString(&text):
            result = .Text(text)

        default:

            identifier.appendContentsOf(bodyFragment as! String)
        }

        consumeOptionalTraillingDot(scanner)

        return .Text(identifier)
    }

    private static let dotCharacterSet = NSCharacterSet(charactersInString: ".")

    private static func consumeOptionalTraillingDot(scanner: NSScanner) {
        scanner.scanCharactersFromSet(dotCharacterSet, intoString: nil)
    }


    private static let singleQuoteDelimittedStringDelimiters = NSCharacterSet(charactersInString:"`'")

    private static func scanSingleQuoteDelimittedString(scanner: NSScanner, inout string: String) throws -> Bool {

        guard scanner.scanString("'", intoString: nil) else {
            return false
        }

        var text = ""
        mainLoop: while !scanner.atEnd {
            //Scan normal text
            var fragment: NSString?
            let didScanFragment = scanner.scanUpToCharactersFromSet(singleQuoteDelimittedStringDelimiters, intoString:&fragment)
            if didScanFragment,
                let fragment = fragment as? String {
                    text.appendContentsOf(fragment)
            }

            //Scan escape sequences
            escapeSequenceLoop: while true {
                if scanner.scanString("`'", intoString: nil) {
                    text.appendContentsOf("'")
                } else if scanner.scanString("``", intoString: nil) {
                    text.appendContentsOf("`")
                } else if scanner.scanString("`", intoString: nil) {
                    text.appendContentsOf("`") //This is technically an invalid escape sequence but we're forgiving.
                } else {
                    break escapeSequenceLoop
                }
            }

            //Attempt to scan the closing delimiter
            if scanner.scanString("'", intoString: nil) {
                //Done!
                string = text
                return true
            }
        }

        throw JSONPath.ParsingError.UnexpectedEndOfString
    }
}


//MARK:- Initialization from string

extension JSONPath {

    /// A cache of the values of each component of a path. The key is the path and the value is an array of NSNumber, NSString and NSNull which represent .Numeric, .Text and .SelfReference respectively.
    private static let componentsCache = NSCache()

    public init(path: String) throws {
        let components: [Component]
