Parser.purs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. module LinkedIn.UIElements.Parser where
  2. import Prelude
  3. import Control.Alt ((<|>))
  4. import Data.Array as A
  5. import Data.Date (Month(..), Year)
  6. import Data.Either (hush)
  7. import Data.Enum (toEnum)
  8. import Data.Int (fromNumber)
  9. import Data.List (List(..), (:))
  10. import Data.List as L
  11. import Data.List.NonEmpty as NEL
  12. import Data.List.Types (NonEmptyList)
  13. import Data.Map (Map)
  14. import Data.Map as M
  15. import Data.Maybe (Maybe(..))
  16. import Data.String as S
  17. import Data.String.CodePoints (codePointFromChar)
  18. import Data.Tuple (Tuple(..))
  19. import LinkedIn.UIElements.Types (Duration(..), JobFlexibility(..), MonthYear(..), MonthYearOrToday(..), TimeSpan(..), UIString(..))
  20. import Parsing (Parser, ParserT, fail, liftMaybe, runParser)
  21. import Parsing.Combinators (choice, try)
  22. import Parsing.String (char, rest, string)
  23. import Parsing.String.Basic (intDecimal, number, space, takeWhile)
  24. monthStrToMonth :: Map String Month
  25. monthStrToMonth = M.fromFoldable (
  26. Tuple "janv." January
  27. : Tuple "fév." February
  28. : Tuple "mars" March
  29. : Tuple "avr." April
  30. : Tuple "mai" May
  31. : Tuple "juin" June
  32. : Tuple "juil." July
  33. : Tuple "août" August
  34. : Tuple "sept." September
  35. : Tuple "oct." October
  36. : Tuple "nov." November
  37. : Tuple "déc." December
  38. : Nil
  39. )
  40. toMonth :: String -> Maybe Month
  41. toMonth month_ = M.lookup month_ monthStrToMonth
  42. toYear :: Number -> Maybe Year
  43. toYear year_ = case fromNumber year_ of
  44. Just y -> toEnum y
  45. Nothing -> Nothing
  46. monthP :: Parser String Month
  47. monthP = do
  48. a <- choice $ string <$> (A.fromFoldable $ M.keys monthStrToMonth)
  49. case toMonth a of
  50. Just month_ -> pure month_
  51. Nothing -> fail "Not a month"
  52. yearP :: Parser String Year
  53. yearP = do
  54. a <- number
  55. case toYear a of
  56. Just year_ -> pure year_
  57. Nothing -> fail "Not a year"
  58. monthYearP :: Parser String MonthYear
  59. monthYearP = do
  60. m <- monthP
  61. _ <- space
  62. y <- yearP
  63. pure $ MonthYear m y
  64. todayP :: Parser String MonthYearOrToday
  65. todayP = do
  66. _ <- string("aujourd’hui")
  67. pure Today
  68. timeSpanP :: Parser String TimeSpan
  69. timeSpanP = do
  70. start <- monthYearP
  71. _ <- space
  72. _ <- char('-')
  73. _ <- space
  74. end <- MY <$> monthYearP <|> todayP
  75. pure $ case end of
  76. Today -> TimeSpanToToday start
  77. MY my -> TimeSpanBounded start my
  78. durationP :: Parser String Duration
  79. durationP = (try yearsMonthP) <|> (try monthsP) <|> yearsP where
  80. yearsInt = do
  81. y <- intDecimal
  82. _ <- space
  83. _ <- try (string("ans")) <|> string("an")
  84. pure y
  85. monthInt = do
  86. m <- intDecimal
  87. _ <- space
  88. _ <- string("mois")
  89. pure m
  90. yearsP = do
  91. y <- yearsInt
  92. pure $ Years y
  93. monthsP = do
  94. y <- monthInt
  95. pure $ Months y
  96. yearsMonthP = do
  97. y <- yearsInt
  98. _ <- space
  99. m <- monthInt
  100. pure $ YearsMonth y m
  101. jobFlexP :: Parser String JobFlexibility
  102. jobFlexP = (try hybrid) <|> (try onSite) <|> (try fullRemote) where
  103. hybrid = do
  104. _ <- string("Hybride")
  105. pure JobFlexHybrid
  106. onSite = do
  107. _ <- string("Sur site")
  108. pure JobFlexOnSite
  109. fullRemote = do
  110. _ <- string("À distance")
  111. pure JobFlexFullRemote
  112. medianDotP ∷ Parser String Char
  113. medianDotP = char('·') <|> char('•')
  114. commaP :: Parser String Char
  115. commaP = char(',')
  116. stringWithoutCommaP :: Parser String String
  117. stringWithoutCommaP = takeWhile (\c -> c /= codePointFromChar ',')
  118. stringWithoutMedianDotP :: Parser String String
  119. stringWithoutMedianDotP = takeWhile (\c -> c /= codePointFromChar '·' && c /= codePointFromChar '•')
  120. uiStringP :: Parser String UIString
  121. uiStringP = (try uiStringdotSeparatedP) <|> uiStringSingleP
  122. uiStringWithoutMedianDotP ∷ Parser String UIString
  123. uiStringWithoutMedianDotP = do
  124. s <- rest
  125. liftMaybe (\_ -> "nope") $ hush $ runParser s uiStringSingleP
  126. uiStringdotSeparatedP ∷ Parser String UIString
  127. uiStringdotSeparatedP = do
  128. Tuple s1 s2 <- medianDotSeparated
  129. let
  130. intoUiElement :: String -> Parser String UIString
  131. intoUiElement s = liftMaybe (\_ -> "could not convert to ui element") $ hush $ runParser s uiStringSingleP
  132. s1' <- intoUiElement s1
  133. s2' <- intoUiElement s2
  134. pure $ UIStringDotSeparated s1' s2'
  135. sepBy2 :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (NonEmptyList a)
  136. sepBy2 p sep = do
  137. a0 <- p
  138. a1 <- sep *> p
  139. as <- L.manyRec $ sep *> p
  140. pure $ NEL.cons a0 $ NEL.cons' a1 as
  141. commaSeparated ∷ Parser String (NonEmptyList String)
  142. commaSeparated = stringWithoutCommaP `sepBy2` commaP
  143. medianDotSeparated ∷ Parser String (Tuple String String)
  144. medianDotSeparated = do
  145. a0 <- stringWithoutMedianDotP
  146. a1 <- medianDotP *> rest
  147. pure $ Tuple (S.trim a0) (S.trim a1)
  148. uiStringSingleP ∷ Parser String UIString
  149. uiStringSingleP = (try uiStringDurationP) <|> (try uiStringTimeSpanP) <|> (try uiStringJobFlexP) <|> uiStringPlainP
  150. uiStringDurationP ∷ Parser String UIString
  151. uiStringDurationP = UIStringDuration <$> durationP
  152. uiStringTimeSpanP ∷ Parser String UIString
  153. uiStringTimeSpanP = UIStringTimeSpan <$> timeSpanP
  154. uiStringJobFlexP ∷ Parser String UIString
  155. uiStringJobFlexP = UIStringJobFlex <$> jobFlexP
  156. uiStringPlainP ∷ Parser String UIString
  157. uiStringPlainP = UIStringPlain <$> rest