Skip to content

Instantly share code, notes, and snippets.

@apraga
Created August 23, 2022 15:06
Show Gist options
  • Save apraga/f57e483e83a131022d895d52b8308fee to your computer and use it in GitHub Desktop.
Save apraga/f57e483e83a131022d895d52b8308fee to your computer and use it in GitHub Desktop.
Parsec example
import qualified Data.Text.IO as TIO
import Data.Maybe
import Data.Time
import Data.Time (defaultTimeLocale)
import Control.Monad
-- show
import Text.Parsec
import Control.Applicative
data Info = Info {
hygrometry :: Float,
temperature :: Float,
pression :: Float,
date :: LocalTime
} deriving (Show)
-- A positive float with a comma instead of a dot
-- Assume there are always decimal !
posFloatC = rd <$> str
where
rd = read :: String -> Float
str = do
d1 <- number
comma <- char ','
d2 <- number
return $ d1 ++ "." ++ d2
number = many1 digit
(<:>) a b = (:) <$> a <*> b
(<++>) a b = (++) <$> a <*> b
-- A positive float with a dot
-- Assume there are always decimal !
posFloat = rd <$> str
where
str = number <++> (char '.' <:> number)
rd = read :: String -> Float
hygrometrieP = do
string "Hygrométrie " *> spaces
f <- posFloatC <* spaces
char '%'
return f
readHygrometry t = do
let s = T.strip . head . filter (T.isInfixOf "Hygrométrie") . T.lines $ t
parse hygrometrieP "readHygrometry" (T.unpack s)
temperatureP = do
string "Température" *> spaces
char ':' *> spaces
f <- posFloatC
spaces *> string "°C"
return f
-- Température : 21,0 °C Pression atm. : 1.013 hPa Eau Ultrapure
readTemperature t = do
let s = head . filter (T.isPrefixOf "Température") . T.lines $ t
parse temperatureP "readTemperature" (T.unpack s)
pressionP = do
string "Pression atm." *> spaces
char ':' *> spaces
f <- posFloat
spaces *> string "hPa"
return f
-- Température : 21,0 °C Pression atm. : 1.013 hPa Eau Ultrapure
readPressure t = do
let s = head . filter (T.isInfixOf "Pression atm.") . T.lines $ t
let s' = T.unpack . snd. T.breakOn "Pression atm" $ s
parse pressionP "readPressure" s'
readDate :: Monad m => T.Text -> m LocalTime
readDate t = do
let s = head . filter (T.isInfixOf "Opérateur") . T.lines $ t
let s' = T.unpack . T.replace ": Le " "" . snd. T.breakOn ": Le " $ s
return $ parseTimeOrError True defaultTimeLocale "%d/%m/%Y %H:%M:%S" s'
parserFloat p l = do
case p l of
Left e -> do
putStrLn "Error parsing input:"
print e
return 99999
Right r -> return r
main = do
l <- TIO.readFile "metrologie.txt"
p <- parserFloat readPressure l
h <- parserFloat readHygrometry l
t <- parserFloat readTemperature l
d <- readDate l
print $ Info h t p d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment