Attempt to parse a list of elements

This commit is contained in:
Joscha 2018-01-04 23:57:02 +00:00
parent 4fd80876f5
commit 81adcb6111
3 changed files with 91 additions and 13 deletions

View file

@ -7,7 +7,6 @@ import Control.Monad
import Control.Monad.Trans.Class import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe import Control.Monad.Trans.Maybe
import Data.Char import Data.Char
import Data.Maybe
import Data.Time import Data.Time
import System.Console.Haskeline import System.Console.Haskeline

View file

@ -25,6 +25,7 @@ dependencies:
- time - time
- transformers - transformers
- haskeline - haskeline
- megaparsec
library: library:
source-dirs: src source-dirs: src

View file

@ -6,6 +6,7 @@ module Cards
, fromCards , fromCards
, elementsToString , elementsToString
, parseElements , parseElements
, parseElementsMaybe
, Card -- Card stuff , Card -- Card stuff
, sides , sides
, tier , tier
@ -21,9 +22,14 @@ module Cards
, testElements , testElements
) where ) where
import Control.Applicative
import Control.Monad
import Data.List import Data.List
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Time import Data.Time
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
-- | Contains 'Card's and comments with a certain ordering. -- | Contains 'Card's and comments with a certain ordering.
-- To update some 'Card's in an 'Elements', use 'toCards' or 'toDueCards' and -- To update some 'Card's in an 'Elements', use 'toCards' or 'toDueCards' and
@ -65,14 +71,14 @@ data Tier = Unrevised
-- Will be removed soon. -- Will be removed soon.
testElements :: Elements testElements :: Elements
testElements = Elements . Map.fromList. zip [1..] $ testElements = Elements . Map.fromList. zip [1..] $
[ card ["first card", "really"] [ ca ["first card", "really"]
, card ["second card", "really"] , ca ["second card", "really"]
, comment "first comment" , co "first comment"
, card ["third card", "really"] , ca ["third card", "really"]
, comment "second comment" , co "second comment"
] ]
where card = ECard . createCard someutctime where ca = ECard . createCard someutctime
comment = EComment co = EComment
someutctime = UTCTime (ModifiedJulianDay 0) (secondsToDiffTime 0) someutctime = UTCTime (ModifiedJulianDay 0) (secondsToDiffTime 0)
{- {-
@ -195,10 +201,10 @@ tierName SixtyFourDays = "64d"
elementsToString :: Elements -> String elementsToString :: Elements -> String
elementsToString (Elements e) = elementsToString (Elements e) =
let elms = map snd $ Map.toList e let elms = map snd $ Map.toList e
in unlines $ intercalate ["", ""] $ map (\x -> [elementToString x]) elms in unlines $ intersperse "" $ map (\x -> elementToString x) elms
elementToString :: Element -> String elementToString :: Element -> String
elementToString (EComment str) = '#' : str elementToString (EComment str) = unlines ['#' : str]
elementToString (ECard card) = cardToString card elementToString (ECard card) = cardToString card
cardToString :: Card -> String cardToString :: Card -> String
@ -207,12 +213,84 @@ cardToString Card{sides=s, tier=t, lastChecked=lc, offset=o} =
", \"last_checked\": " ++ (show $ formatTime defaultTimeLocale "%s" lc) ++ ", \"last_checked\": " ++ (show $ formatTime defaultTimeLocale "%s" lc) ++
", \"delay\": " ++ (show $ fromEnum o) ++ ", \"delay\": " ++ (show $ fromEnum o) ++
"}" "}"
in unlines $ info : intersperse "::" s ++ [""] -- newline at the end in unlines $ info : intersperse "::" s
{- {-
- Parsing - Parsing
-} -}
-- | Not yet implemented. -- | Not yet implemented.
parseElements :: String -> Maybe Elements type Parser = Parsec Void String
parseElements = undefined
-- useful parsers
followedBy :: Parser a -> Parser ()
followedBy = void . try . lookAhead
-- separates sides of cards
cardSeparator :: Parser String
cardSeparator = string "::" <?> "card separator"
-- separates elements
separator :: Parser ()
separator = void newline <|> void eof <?> "separator"
-- infostring
infostring :: UTCTime -> Parser Card
infostring time = do
_ <- string ":: "
card <- between (string "{") (string "}") (innerinfo time)
return card
-- TODO: implement
innerinfo :: UTCTime -> Parser Card
innerinfo = undefined
-- sides of a card
side :: Parser String
side = anyChar `manyTill` followedBy end
where end = newline >> (void cardSeparator <|> void separator)
pSides :: Parser [String]
pSides = side `sepBy1` (try $ newline >> cardSeparator >> newline)
-- an actual card
pCard :: UTCTime -> Parser Card
pCard time = cardInfo time <|> cardNoInfo time
cardInfo :: UTCTime -> Parser Card
cardInfo time = do
Card{tier=t, lastChecked=lc, offset=o} <- infostring time
_ <- newline
s <- pSides
return Card{sides=s, tier=t, lastChecked=lc, offset=o}
cardNoInfo :: UTCTime -> Parser Card
cardNoInfo time = do
s <- pSides
return $ createCard time s
-- an element
comment :: Parser Element
comment = char '#' >> EComment <$> (anyChar `manyTill` followedBy end)
where end = newline >> separator
element :: UTCTime -> Parser Element
element time = comment <|> (ECard <$> pCard time) <?> "element"
-- a bunch of elements
--line :: Parser Element
--line = EComment <$> manyTill anyChar newline
parseElements :: UTCTime -> Parser [Element]
parseElements time = sepEndBy (element time) (some newline) <* eof
parseElementsMaybe :: UTCTime -> String -> Maybe Elements
parseElementsMaybe time str = do
elms <- parseMaybe (parseElements time) str
return $ Elements $ Map.fromList $ zip [1..] elms