module Text.Printf.TH.Parser where
import Control.Applicative
import Data.CharSet (fromList)
import Text.Trifecta
import qualified Data.Set as S
import Text.Printf.TH.Types
flagSet = fromList "-+ #0"
specSet = fromList "diuoxXfFeEaAgGpcs?"
parseFmtStr = do
atoms <-
many $
choice [Str "%" <$ string "%%", Arg <$> fmtArg, Str . return <$> noneOf "%"]
return $ go atoms
where
go (Str s:Str s1:as) = go (Str (s ++ s1) : as)
go (a:as) = a : go as
go [] = []
fmtArg = do
char '%'
flags <-
do fs <-
many $ do
c <- oneOfSet flagSet <?> "flag"
pure $
case c of
'-' -> FlagLJust
'+' -> FlagSigned
' ' -> FlagSpaced
'#' -> FlagPrefixed
'0' -> FlagZeroPadded
_ -> error "???"
let flagSet = S.fromList fs
if S.size flagSet < length fs
then fail "Duplicate flags specified"
else pure $ toFlagSet flagSet
width <- optional $ choice [Given <$> natural, Need <$ char '*'] <?> "width"
precision <-
optional $
(do char '.'
choice [Given <$> natural, Need <$ char '*']) <?>
"precision"
spec <- oneOfSet specSet <?> "valid specifier"
pure $ FormatArg flags width precision spec