sequitur-0.2.0.0: app/demo/Main.hs
{-# OPTIONS_GHC -Wall #-}
module Main (main) where
import Control.Monad
import qualified Data.IntMap.Strict as IntMap
import Data.List (intercalate)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Language.Grammar.Sequitur as Sequitur
import Options.Applicative
import System.Clock
import Text.Printf
data Options
= Options
{ optInputFile :: FilePath
, optPrintGrammar :: Bool
}
optionsParser :: Parser Options
optionsParser = Options
<$> inputFile
<*> printGrammar
where
inputFile = strArgument
$ metavar "FILE"
<> help "input filename"
printGrammar = flag True False
$ long "no-grammar"
<> help "do not print resulting grammar"
parserInfo :: ParserInfo Options
parserInfo = info (optionsParser <**> helper)
$ fullDesc
<> header "sequitur-demo"
main :: IO ()
main = do
opt <- execParser parserInfo
-- To benchmark time without I/O, we read a file beforehand using strict I/O.
s <- T.readFile (optInputFile opt)
startCPU <- getTime ProcessCPUTime
startWC <- getTime Monotonic
builder <- Sequitur.newBuilder
forM_ (T.unpack s) $ \c -> do
Sequitur.add builder c
Sequitur.Grammar m <- Sequitur.build builder
endCPU <- getTime ProcessCPUTime
endWC <- getTime Monotonic
printf "cpu time = %.3fs\n" (durationSecs startCPU endCPU)
printf "wall clock time = %.3fs\n" (durationSecs startWC endWC)
when (optPrintGrammar opt) $ do
forM_ (IntMap.toList m) $ \(r, body) -> do
let f (Sequitur.Terminal c) = show c
f (Sequitur.NonTerminal r') = show r'
putStrLn $ show r ++ " -> " ++ intercalate " " (map f body)
return ()
durationSecs :: TimeSpec -> TimeSpec -> Double
durationSecs start end = fromIntegral (toNanoSecs (end `diffTimeSpec` start)) / 10^(9::Int)