/* Generated by re2swift */
#sourceLocation(file: "swift/fill/01_fill.re", line: 1)
// re2swift $INPUT -o $OUTPUT
import Foundation

struct Input {
  static let bufferSize = 4095

  var file: FileHandle

  var yyinput  = ContiguousArray<UInt8>(repeating: 0, count: Self.bufferSize + 1)
  var yylimit  = Self.bufferSize
  var yycursor = Self.bufferSize
  var yymarker = Self.bufferSize
  var token    = -1
  var eof      = false
}

extension Input {
  mutating func lex() -> Int? {
    var count = 0
    loop: while true {
      self.token = self.yycursor
      
#sourceLocation(file: "swift/fill/01_fill.swift", line: 26)
  var yych: UInt8 = 0
  var yystate: UInt = 0
  yyl: while true {
    switch yystate {
      case 0:
        yych = self.yyinput[self.yycursor]
        switch yych {
          case 0x20:
            self.yycursor += 1
            yystate = 3
            continue yyl
          case 0x27:
            self.yycursor += 1
            yystate = 5
            continue yyl
          default:
            if self.yylimit <= self.yycursor {
              if self.fill() == .ok {
                yystate = 0
                continue yyl
              }
              yystate = 10
              continue yyl
            }
            self.yycursor += 1
            yystate = 1
            continue yyl
        }
      case 1:
        yystate = 2
        continue yyl
      case 2:
#sourceLocation(file: "swift/fill/01_fill.re", line: 36)
        return nil
#sourceLocation(file: "swift/fill/01_fill.swift", line: 61)
      case 3:
        yych = self.yyinput[self.yycursor]
        switch yych {
          case 0x20:
            self.yycursor += 1
            yystate = 3
            continue yyl
          default:
            if self.yylimit <= self.yycursor {
              if self.fill() == .ok {
                yystate = 3
                continue yyl
              }
            }
            yystate = 4
            continue yyl
        }
      case 4:
#sourceLocation(file: "swift/fill/01_fill.re", line: 34)
        continue loop
#sourceLocation(file: "swift/fill/01_fill.swift", line: 82)
      case 5:
        self.yymarker = self.yycursor
        yych = self.yyinput[self.yycursor]
        if yych >= 0x01 {
          yystate = 7
          continue yyl
        }
        if self.yylimit <= self.yycursor {
          if self.fill() == .ok {
            yystate = 5
            continue yyl
          }
          yystate = 2
          continue yyl
        }
        self.yycursor += 1
        yystate = 6
        continue yyl
      case 6:
        yych = self.yyinput[self.yycursor]
        yystate = 7
        continue yyl
      case 7:
        switch yych {
          case 0x27:
            self.yycursor += 1
            yystate = 8
            continue yyl
          case 0x5C:
            self.yycursor += 1
            yystate = 9
            continue yyl
          default:
            if self.yylimit <= self.yycursor {
              if self.fill() == .ok {
                yystate = 6
                continue yyl
              }
              yystate = 11
              continue yyl
            }
            self.yycursor += 1
            yystate = 6
            continue yyl
        }
      case 8:
#sourceLocation(file: "swift/fill/01_fill.re", line: 30)
        
          count += 1
          continue loop

#sourceLocation(file: "swift/fill/01_fill.swift", line: 134)
      case 9:
        yych = self.yyinput[self.yycursor]
        if yych <= 0x00 {
          if self.yylimit <= self.yycursor {
            if self.fill() == .ok {
              yystate = 9
              continue yyl
            }
            yystate = 11
            continue yyl
          }
          self.yycursor += 1
          yystate = 6
          continue yyl
        }
        self.yycursor += 1
        yystate = 6
        continue yyl
      case 10:
#sourceLocation(file: "swift/fill/01_fill.re", line: 35)
        return count
#sourceLocation(file: "swift/fill/01_fill.swift", line: 156)
      case 11:
        self.yycursor = self.yymarker
        yystate = 2
        continue yyl
      default: fatalError("internal lexer error")
    }
  }
#sourceLocation(file: "swift/fill/01_fill.re", line: 37)

    }
  }

  mutating func fill() -> FillStatus {
    guard !self.eof else {
      return .eof
    }

    let shift = self.token
    let used = self.yylimit - self.token
    let free = Self.bufferSize - used

    // Error: Lexeme too long. In the real world we can reallocate a larger buffer.
    if self.token < 1 {
      return .longLexeme
    }

    // Shift buffer contents, discarding everything up to the current lexeme.
    self.yyinput.replaceSubrange(..<used, with: self.yyinput[shift..<self.yylimit])
    self.yylimit  -= shift
    self.yycursor -= shift
    self.yymarker &-= shift  // May underflow if marker is unused
    self.token = 0

    // Fill free space at the end of buffer with new data from file.
    do {
      if let data = try self.file.read(upToCount: free) {
        self.yyinput.replaceSubrange(self.yylimit..<(self.yylimit + data.count), with: data)
        self.yylimit += data.count
      }
    } catch {
      fatalError("cannot read from file: \(error.localizedDescription)")
    }
    self.yyinput[self.yylimit] = 0  // append sentinel
    self.eof = self.yylimit < Self.bufferSize

    return .ok
  }

  enum FillStatus {
    case ok, eof, longLexeme
  }
}

let fileName = "input"
let content = "'qu\0tes' 'are' 'fine: \\'' "

// Prepare input file: a few times the size of the buffer,
// containing strings with zeroes and escaped quotes.
guard FileManager.default.createFile(
    atPath: fileName,
    contents: Data(String(repeating: content, count: Input.bufferSize).utf8)
) else {
  fatalError("failed to write file \"\(fileName)\"")
}

// Number of quoted strings written to file
let count = 3 * Input.bufferSize

// Initialize lexer state
guard let file = FileHandle(forReadingAtPath: fileName) else {
  throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadNoSuchFile.rawValue)
}
var `in` = Input(file: file)

// Run the lexer
assert(`in`.lex() == count)

// Cleanup: remove input file
try file.close()
try FileManager.default.removeItem(atPath: fileName)
