-- Generated by re2hs
{-# LANGUAGE RecordWildCards #-}
#1 "haskell/fill/01_fill.re"
-- re2hs $INPUT -o $OUTPUT
{-# OPTIONS_GHC -Wno-unused-record-wildcards #-}
{-# LANGUAGE OverloadedStrings #-}

import Control.Monad
import Data.ByteString as BS
import Data.Word
import GHC.IO.Handle
import System.Directory
import System.IO

chunk_size :: Int
chunk_size = 4096

data State = State {
    _file :: !Handle,
    _yyinput :: !BS.ByteString,
    _yycursor :: !Int,
    _yymarker :: !Int,
    _yylimit :: !Int,
    _token :: !Int,
    _eof :: !Bool,
    _count :: !Int
}


#31 "haskell/fill/01_fill.hs"
yy0 :: State -> IO Int
yy0 !State{..} = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x20 == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy3 State{..}
        _c | 0x27 == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy5 State{..}
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy0 State{..}
                else yy10 State{..}
            else do
                _yycursor <- return $ _yycursor + 1
                yy1 State{..}

yy1 :: State -> IO Int
yy1 !State{..} = do
    yy2 State{..}

yy2 :: State -> IO Int
yy2 !State{..} = do
#36 "haskell/fill/01_fill.re"
    return (-1)
#59 "haskell/fill/01_fill.hs"

yy3 :: State -> IO Int
yy3 !State{..} = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x20 == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy3 State{..}
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy3 State{..}
                else yy4 State{..}
            else do
                yy4 State{..}

yy4 :: State -> IO Int
yy4 !State{..} = do
#39 "haskell/fill/01_fill.re"
    lexer State{_token = _yycursor, ..}
#80 "haskell/fill/01_fill.hs"

yy5 :: State -> IO Int
yy5 !State{..} = do
    let _yymarker = _yycursor
    yych <- return $ BS.index _yyinput _yycursor
    if yych <= 0x00 then do
        if _yycursor >= _yylimit then do
            (State{..}, yyfill) <- fill State{..}
            if yyfill then yy5 State{..}
            else yy2 State{..}
        else do
            _yycursor <- return $ _yycursor + 1
            yy6 State{..}
    else do
        yy7 State{..} yych

yy6 :: State -> IO Int
yy6 !State{..} = do
    yych <- return $ BS.index _yyinput _yycursor
    yy7 State{..} yych

yy7 :: State -> Word8 -> IO Int
yy7 !State{..} yych = do
    case yych of
        _c | 0x27 == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy8 State{..}
        _c | 0x5C == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy9 State{..}
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy6 State{..}
                else yy11 State{..}
            else do
                _yycursor <- return $ _yycursor + 1
                yy6 State{..}

yy8 :: State -> IO Int
yy8 !State{..} = do
#38 "haskell/fill/01_fill.re"
    lexer State{_token = _yycursor, _count = _count + 1, ..}
#124 "haskell/fill/01_fill.hs"

yy9 :: State -> IO Int
yy9 !State{..} = do
    yych <- return $ BS.index _yyinput _yycursor
    if yych <= 0x00 then do
        if _yycursor >= _yylimit then do
            (State{..}, yyfill) <- fill State{..}
            if yyfill then yy9 State{..}
            else yy11 State{..}
        else do
            _yycursor <- return $ _yycursor + 1
            yy6 State{..}
    else do
        _yycursor <- return $ _yycursor + 1
        yy6 State{..}

yy10 :: State -> IO Int
yy10 !State{..} = do
#37 "haskell/fill/01_fill.re"
    return _count
#145 "haskell/fill/01_fill.hs"

yy11 :: State -> IO Int
yy11 !State{..} = do
    let _yycursor = _yymarker
    yy2 State{..}

lexer :: State -> IO Int
lexer !State{..} = do
    yy0 State{..}

#40 "haskell/fill/01_fill.re"


fill :: State -> IO (State, Bool)
fill State{..} = do
    case _eof of
        True -> return (State{..}, False)
        False -> do
            -- Discard everything up to the current token, cut off terminating null,
            -- read new chunk from file and reappend terminating null at the end.
            chunk <- BS.hGet _file chunk_size
            return (State {
                _yyinput = BS.concat [(BS.init . BS.drop _token) _yyinput, chunk, "\0"],
                _yycursor = _yycursor - _token,
                _yymarker = _yymarker - _token,
                _yylimit = _yylimit - _token + BS.length chunk, -- exclude terminating null
                _token = 0,
                _eof = BS.null chunk, -- end of file?
                ..}, True)

main :: IO ()
main = do
    let fname = "input"

    -- Prepare input file.
    BS.writeFile fname $ BS.concat ["'qu\0tes' 'are' 'fine: \\'' " | _ <- [1..chunk_size]]
    let expect = 3 * chunk_size -- the total number of strings in file

    -- Run lexer on the prepared file.
    fh <- openFile fname ReadMode
    let st = State {
        _file = fh,
        _yyinput = BS.singleton 0,
        _yycursor = 0,
        _yymarker = 0,
        _token = 0,
        _yylimit = 0,
        _eof = False,
        _count = 0
    }
    result <- lexer st
    hClose fh

    -- Cleanup.
    removeFile fname

    -- Check result.
    when (result /= expect) $ error $ "expected " ++ show expect ++ ", got " ++ show result
    return ()
