--	RegexPRTypes.hs
--
--	Author: Yoshikuni Jujo <PAF01143@nifty.ne.jp>
--

module Hidden.RegexPRTypes (
  reverseRegexAction
, RegexSrcParser
, getBR
, modifyBR
, isModeI
, isModeM
, isModeX
, setMode
, runRegexSrcParser
, RegexAction(..)

, RegexResult
, MatchList
, RegexParser
, runRegexParser
) where

import Hidden.ParseLib( Parse, runParse )
import Control.Monad.State( StateT, runStateT, gets, modify )
import Control.Monad.Reader( ReaderT(runReaderT) )
import Hidden.Tools( modifySnd, modifyFst,
                     first, second, third,
		     modifyFirst, modifySecond, modifyThird )

type RegexResult = ( String, (String, String) )
type MatchList   = [ (Int, String) ]
type RegexParser = ReaderT (String, String) (StateT MatchList (Parse Char))
runRegexParser ::
  (String, String) ->
  RegexParser a -> (String, String) -> [((a, MatchList), (String, String))]
runRegexParser point = runParse . flip runStateT [] . flip runReaderT point

type RegexSrcParser = StateT (Int, (Bool, Bool, Bool)) (Parse Char)

getBR :: RegexSrcParser Int
getBR    = gets fst

modifyBR :: (Int -> Int) -> RegexSrcParser ()
modifyBR = modify . modifyFst

setMode :: Char -> Bool -> RegexSrcParser ()
setMode 'i' = modify . modifySnd . modifyFirst  . const
setMode 'm' = modify . modifySnd . modifySecond . const
setMode 'x' = modify . modifySnd . modifyThird  . const
setMode m   = error $ "no " ++ [m] ++ " mode"

isModeI, isModeM, isModeX :: RegexSrcParser Bool
isModeI = gets $ first  . snd
isModeM = gets $ second . snd
isModeX = gets $ third  . snd
runRegexSrcParser :: RegexSrcParser a -> Parse Char (a, (Int,(Bool,Bool,Bool)))
runRegexSrcParser = flip runStateT (1, (False, False, False))

data RegexAction = Select (Char -> Bool)                           |
                   Repeat          Int (Maybe Int) RegexAction     |
                   RepeatNotGreedy Int (Maybe Int) RegexAction     |
		   RegexOr [RegexAction] [RegexAction]             |
                   Note Int [RegexAction] | BackReference Int      |
		   Still [RegexAction]    | Backword [RegexAction] |
		   RegActNot [RegexAction]                         |
		   BeginningOfInput       | EndOfInput             |
		   PreMatchPoint          | Parens [RegexAction]   |
		   Comment String         | NopRegex               |
		   NoBacktrack [RegexAction]

reverseRegexAction :: RegexAction -> RegexAction
reverseRegexAction (Note i ras)
  = Note i $ reverse $ map reverseRegexAction ras
reverseRegexAction (RegexOr ras1 ras2)
  = RegexOr (reverse $ map reverseRegexAction ras1)
            (reverse $ map reverseRegexAction ras2)
-- reverseRegexAction (Still ras)
--  = Still $ reverse $ map reverseRegexAction ras
-- reverseRegexAction (Backword ras)
--  = Backword $ reverse $ map reverseRegexAction ras
reverseRegexAction ra = ra