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

import Control.Monad
import Data.ByteString as BS
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,
    -- Final tag bindings available in semantic action.
    
#27 "haskell/submatch/01_stags_fill.hs"

_1 :: !Int,
_2 :: !Int,
_3 :: !Int,
_4 :: !Int,
_5 :: !Int,
#22 "haskell/submatch/01_stags_fill.re"

    -- Intermediate tag bindings used by the lexer (must be autogenerated).
    
#38 "haskell/submatch/01_stags_fill.hs"

_yyt1 :: !Int,
_yyt2 :: !Int,
_yyt3 :: !Int,
_yyt4 :: !Int,
#24 "haskell/submatch/01_stags_fill.re"

    _eof :: !Bool
}

data SemVer = SemVer {
    major :: !Int,
    minor :: !Int,
    patch :: !Int
} deriving (Eq, Show)

s2n :: BS.ByteString -> Int -> Int -> Int
s2n s i j = f i 0 where
    f k n = if k >= j then n else f (k + 1) (n * 10 + (fromIntegral (BS.index s k) - 48))


#60 "haskell/submatch/01_stags_fill.hs"
yy0 :: State -> [SemVer] -> IO [SemVer]
yy0 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x30 <= _c && _c <= 0x39 -> do
            let _yyt1 = _yycursor
            _yycursor <- return $ _yycursor + 1
            yy3 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy0 State{..} _vers
                else yy11 State{..} _vers
            else do
                _yycursor <- return $ _yycursor + 1
                yy1 State{..} _vers

yy1 :: State -> [SemVer] -> IO [SemVer]
yy1 State{..} _vers = do
    yy2 State{..} _vers

yy2 :: State -> [SemVer] -> IO [SemVer]
yy2 State{..} _vers = do
#57 "haskell/submatch/01_stags_fill.re"
    error "lexer failed"
#86 "haskell/submatch/01_stags_fill.hs"

yy3 :: State -> [SemVer] -> IO [SemVer]
yy3 State{..} _vers = do
    let _yymarker = _yycursor
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x2E == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy4 State{..} _vers
        _c | 0x30 <= _c && _c <= 0x39 -> do
            _yycursor <- return $ _yycursor + 1
            yy6 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy3 State{..} _vers
                else yy2 State{..} _vers
            else do
                yy2 State{..} _vers

yy4 :: State -> [SemVer] -> IO [SemVer]
yy4 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x30 <= _c && _c <= 0x39 -> do
            let _yyt2 = _yycursor
            _yycursor <- return $ _yycursor + 1
            yy7 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy4 State{..} _vers
                else yy5 State{..} _vers
            else do
                yy5 State{..} _vers

yy5 :: State -> [SemVer] -> IO [SemVer]
yy5 State{..} _vers = do
    let _yycursor = _yymarker
    yy2 State{..} _vers

yy6 :: State -> [SemVer] -> IO [SemVer]
yy6 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x2E == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy4 State{..} _vers
        _c | 0x30 <= _c && _c <= 0x39 -> do
            _yycursor <- return $ _yycursor + 1
            yy6 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy6 State{..} _vers
                else yy5 State{..} _vers
            else do
                yy5 State{..} _vers

yy7 :: State -> [SemVer] -> IO [SemVer]
yy7 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x0A == _c -> do
            let _yyt3 = _yycursor
            let _yyt4 = (-1)
            _yycursor <- return $ _yycursor + 1
            yy8 State{..} _vers
        _c | 0x2E == _c -> do
            let _yyt3 = _yycursor
            _yycursor <- return $ _yycursor + 1
            yy9 State{..} _vers
        _c | 0x30 <= _c && _c <= 0x39 -> do
            _yycursor <- return $ _yycursor + 1
            yy7 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy7 State{..} _vers
                else yy5 State{..} _vers
            else do
                yy5 State{..} _vers

yy8 :: State -> [SemVer] -> IO [SemVer]
yy8 State{..} _vers = do
    let _1 = _yyt1
    let _3 = _yyt2
    let _4 = _yyt3
    let _5 = _yyt4
    let _2 = _yyt2
    _2 <- return $ if _2 == (-1) then (-1) else _2 - 1
#48 "haskell/submatch/01_stags_fill.re"
    let ver = SemVer {
        major = s2n _yyinput _1 _2,
        minor = s2n _yyinput _3 _4,
        patch = if _5 == (-1) then 0 else s2n _yyinput _5 (_yycursor - 1)
    }
    lexer State{..} (ver: _vers)
#185 "haskell/submatch/01_stags_fill.hs"

yy9 :: State -> [SemVer] -> IO [SemVer]
yy9 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x30 <= _c && _c <= 0x39 -> do
            let _yyt4 = _yycursor
            _yycursor <- return $ _yycursor + 1
            yy10 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy9 State{..} _vers
                else yy5 State{..} _vers
            else do
                yy5 State{..} _vers

yy10 :: State -> [SemVer] -> IO [SemVer]
yy10 State{..} _vers = do
    yych <- return $ BS.index _yyinput _yycursor
    case yych of
        _c | 0x0A == _c -> do
            _yycursor <- return $ _yycursor + 1
            yy8 State{..} _vers
        _c | 0x30 <= _c && _c <= 0x39 -> do
            _yycursor <- return $ _yycursor + 1
            yy10 State{..} _vers
        _c | True -> do
            if _yycursor >= _yylimit then do
                (State{..}, yyfill) <- fill State{..}
                if yyfill then yy10 State{..} _vers
                else yy5 State{..} _vers
            else do
                yy5 State{..} _vers

yy11 :: State -> [SemVer] -> IO [SemVer]
yy11 State{..} _vers = do
#56 "haskell/submatch/01_stags_fill.re"
    return _vers
#225 "haskell/submatch/01_stags_fill.hs"

lexer :: State -> [SemVer] -> IO [SemVer]
lexer State{..} _vers = do
    yy0 State{..} _vers

#58 "haskell/submatch/01_stags_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 ["1.22.333\n" | _ <- [1..chunk_size]]
    let expect = [SemVer {major = 1, minor = 22, patch = 333} | _ <- [1..chunk_size]]

    -- Run lexer on the prepared file.
    fh <- openFile fname ReadMode
    let st = State {
        _file = fh,
        _yyinput = BS.singleton 0,
        _yycursor = 0,
        _yymarker = 0,
        _yylimit = 0,
        _token = 0,
        
#269 "haskell/submatch/01_stags_fill.hs"

_1 = (-1),
_2 = (-1),
_3 = (-1),
_4 = (-1),
_5 = (-1),
#94 "haskell/submatch/01_stags_fill.re"

        
#279 "haskell/submatch/01_stags_fill.hs"

_yyt1 = (-1),
_yyt2 = (-1),
_yyt3 = (-1),
_yyt4 = (-1),
#95 "haskell/submatch/01_stags_fill.re"

        _eof = False
    }
    result <- lexer st []
    hClose fh

    -- Cleanup.
    removeFile fname

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