     var tokens: [Token] = []
 
     let scanner = Scanner(templateString)
-
-    let map = [
-      "{{": "}}",
-      "{%": "%}",
-      "{#": "#}",
-      ]
-
     while !scanner.isEmpty {
-      if let text = scanner.scan(until: ["{{", "{%", "{#"]) {
-        if !text.1.isEmpty {
-          tokens.append(createToken(string: text.1, at: scanner.range))
+      if let (char, text) = scanner.scanForTokenStart(Lexer.tokenChars) {
+        if !text.isEmpty {
+          tokens.append(createToken(string: text, at: scanner.range))
         }
 
-        let end = map[text.0]!
-        let result = scanner.scan(until: end, returnUntil: true)
+        guard let end = Lexer.tokenCharMap[char] else { continue }
+        let result = scanner.scanForTokenEnd(end)
         tokens.append(createToken(string: result, at: scanner.range))
       } else {
         tokens.append(createToken(string: scanner.content, at: scanner.range))

  func createToken(string: String, at range: Range<String.Index>) -> Token {
    func strip() -> String {
      guard string.count > 4 else { return "" }
      let start = string.index(string.startIndex, offsetBy: 2)
      let end = string.index(string.endIndex, offsetBy: -2)
      let trimmed = String(string[start..<end])
        .components(separatedBy: "\n")
        .filter({ !$0.isEmpty })
        .map({ $0.trim(character: " ") })

  let templateName: String?
  let templateString: String
  let lines: [Line]

  private static let tokenChars: [Unicode.Scalar] = ["{", "%", "#"]
  private static let tokenCharMap: [Unicode.Scalar: Unicode.Scalar] = [
    "{": "}",
    "%": "%",
    "#": "#"
  ]

  init(templateName: String? = nil, templateString: String) {
    self.templateName = templateName
