{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- |
-- Module      :  Interpreter.StringConversion
-- Copyright   :  (c) OleksandrZhabenko 2021
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- A library that has commonly used function for the phonetic-languages implementations.

module Interpreter.StringConversion where

import Text.Read (readMaybe)
import Data.Maybe (fromJust,fromMaybe)
import Data.Char (isDigit)
import Data.List (sort,(\\))
import Data.Monoid (mappend)
import Control.Exception

{-| Converts the second given string into the form that can be easily used by the phonetic-languages-simplified-* implementations. -}
convStringInterpreter :: String -> String -> String
convStringInterpreter :: String -> String -> String
convStringInterpreter String
contrs String
xs
 | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
contrs = String
xs
 | [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> (String -> [String]) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
xs = String
xs
 | case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/' Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-') String
contrs of { Char
a:Char
'/':String
bs -> Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/' Bool -> Bool -> Bool
&& Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'0' ; ~String
rrr -> Bool
False } =
     let ys :: String
ys = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/') String
contrs in
       case String
ys of
         ~Char
a:Char
'/':String
bs -> let wordsN :: [String]
wordsN = String -> [String]
words String
xs
                          wordN :: Int
wordN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
a]::Maybe Int)) ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
wordsN)
                          pos :: Int
pos = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe String
bs::Maybe Int)
                          wrdP :: String
wrdP = [String]
wordsN [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
                          (String
ts,String
us) | Int
pos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
wrdP
                                  | Bool
otherwise = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
wrdP Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
pos) String
wrdP
                          twoWords :: String
twoWords = String
ts String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
us)
                          ([String]
wss,[String]
tss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
wordsN
                          kss :: [String]
kss = Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 [String]
tss in
                            if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
wss then String
twoWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss)
                            else [String] -> String
unwords [String]
wss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
twoWords) String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss)
 | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = String
xs
 | Bool
otherwise = let cntrs :: String
cntrs = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs
                   tss :: [String]
tss = String -> [String]
words String
xs in
                     case String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
cntrs of
                      Int
2 -> let pos :: Int
pos = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cntrs)::Maybe Int)
                               number :: Int
number = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
cntrs)::Maybe Int)
                               ([String]
zss,[String]
yss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
tss
                               ([String]
kss,[String]
lss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
number [String]
yss in
                                 if [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
tss Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
number Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 then String
xs
                                 else if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
zss then [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss
                                      else [String] -> String
unwords [String]
zss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss
                      Int
_ -> let idxs :: [Int]
idxs = (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Char
x -> Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
x]::Maybe Int)) (String -> [Int]) -> String -> [Int]
forall a b. (a -> b) -> a -> b
$ String
cntrs
                               wordsN :: [String]
wordsN = (Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i -> [String]
tss [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) [Int]
idxs
                               restWords :: [String]
restWords = [String]
tss [String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
wordsN
                                 in [String] -> String
unwords [String]
restWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
wordsN

{-| Inspired by: 'https://hackage.haskell.org/package/base-4.15.0.0/docs/src/GHC-IO.html#catch'
Reads a textual file given by its 'FilePath' and returns its contents lazily. If there is
some 'IOException' thrown or an empty file then returns just "". Raises an exception for the binary file. -}
readFileIfAny :: FilePath -> IO String
readFileIfAny :: String -> IO String
readFileIfAny String
file = IO String -> (IOException -> IO String) -> IO String
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (String -> IO String
readFile String
file) (\(IOException
e :: IOException) -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
"")

-------------------------------------------------------------

argsConvertTextual :: String -> [String] -> [String]
argsConvertTextual :: String -> [String] -> [String]
argsConvertTextual String
ts [String]
tss
 | (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
ts) [String]
tss = [String]
tss
 | Bool
otherwise = [String]
tss [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` [String
ts]
{-# INLINE argsConvertTextual #-}

fullArgsConvertTextual
  :: (String -> Bool) -- ^ The predicate that checks whether the given argument is not a phonetic language word in the representation.
  -> String
  -> String
  -> [String]
  -> [String]
fullArgsConvertTextual :: (String -> Bool) -> String -> String -> [String] -> [String]
fullArgsConvertTextual String -> Bool
p String
textProcessment0 String
lineA [String]
args =
  String -> [String] -> [String]
argsConvertTextual String
textProcessment0 ((String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile String -> Bool
p [String]
args [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` String -> [String]
words String
lineA)
{-# INLINE fullArgsConvertTextual #-}

-------------------------------------------------------------

fullArgsConvertTextualSimple
  :: (String -> Bool) -- ^ The predicate that checks whether the given argument is not a phonetic language word in the representation.
  -> String
  -> [String]
  -> [String]
fullArgsConvertTextualSimple :: (String -> Bool) -> String -> [String] -> [String]
fullArgsConvertTextualSimple String -> Bool
p String
lineA [String]
args = (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile String -> Bool
p [String]
args [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` String -> [String]
words String
lineA
{-# INLINE fullArgsConvertTextualSimple #-}