Parser.purs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 (Either(..))
  7. import Data.Enum (toEnum)
  8. import Data.Int (fromNumber)
  9. import Data.List (List(..), (:))
  10. import Data.Map (Map)
  11. import Data.Map as M
  12. import Data.Maybe (Maybe(..))
  13. import Data.String.CodePoints (codePointFromChar)
  14. import Data.Tuple (Tuple(..))
  15. import LinkedIn.UIElements.Types (Duration(..), MonthYear(..), MonthYearOrToday(..), TimeSpan(..), UIElement(..))
  16. import Parsing (Parser, fail, runParser)
  17. import Parsing.Combinators (choice, try)
  18. import Parsing.String (string, char, rest)
  19. import Parsing.String.Basic (intDecimal, number, space, takeWhile)
  20. monthStrToMonth :: Map String Month
  21. monthStrToMonth = M.fromFoldable (
  22. Tuple "janv." January
  23. : Tuple "fév." February
  24. : Tuple "mars" March
  25. : Tuple "avr." April
  26. : Tuple "mai" May
  27. : Tuple "juin" June
  28. : Tuple "juil." July
  29. : Tuple "août" August
  30. : Tuple "sept." September
  31. : Tuple "oct." October
  32. : Tuple "nov." November
  33. : Tuple "déc." December
  34. : Nil
  35. )
  36. toMonth :: String -> Maybe Month
  37. toMonth month_ = M.lookup month_ monthStrToMonth
  38. toYear :: Number -> Maybe Year
  39. toYear year_ = case fromNumber year_ of
  40. Just y -> toEnum y
  41. Nothing -> Nothing
  42. monthP :: Parser String Month
  43. monthP = do
  44. a <- choice $ string <$> (A.fromFoldable $ M.keys monthStrToMonth)
  45. case toMonth a of
  46. Just month_ -> pure month_
  47. Nothing -> fail "Not a month"
  48. yearP :: Parser String Year
  49. yearP = do
  50. a <- number
  51. case toYear a of
  52. Just year_ -> pure year_
  53. Nothing -> fail "Not a year"
  54. monthYearP :: Parser String MonthYear
  55. monthYearP = do
  56. m <- monthP
  57. _ <- space
  58. y <- yearP
  59. pure $ MonthYear m y
  60. todayP :: Parser String MonthYearOrToday
  61. todayP = do
  62. _ <- string("aujourd’hui")
  63. pure Today
  64. timeSpanP :: Parser String TimeSpan
  65. timeSpanP = do
  66. start <- monthYearP
  67. _ <- space
  68. _ <- char('-')
  69. _ <- space
  70. end <- MY <$> monthYearP <|> todayP
  71. pure $ case end of
  72. Today -> TimeSpanToToday start
  73. MY my -> TimeSpanBounded start my
  74. durationP :: Parser String Duration
  75. durationP = (try yearsMonthP) <|> (try monthsP) <|> yearsP where
  76. yearsInt = do
  77. y <- intDecimal
  78. _ <- space
  79. _ <- try (string("ans")) <|> string("an")
  80. pure y
  81. monthInt = do
  82. m <- intDecimal
  83. _ <- space
  84. _ <- string("mois")
  85. pure m
  86. yearsP = do
  87. y <- yearsInt
  88. pure $ Years y
  89. monthsP = do
  90. y <- monthInt
  91. pure $ Months y
  92. yearsMonthP = do
  93. y <- yearsInt
  94. _ <- space
  95. m <- monthInt
  96. pure $ YearsMonth y m
  97. medianDotP ∷ Parser String Char
  98. medianDotP = char('·') <|> char('•')
  99. commaP :: Parser String Char
  100. commaP = char(',')
  101. stringWithoutCommaP :: Parser String String
  102. stringWithoutCommaP = takeWhile (\c -> c /= codePointFromChar ',')
  103. stringWithoutMedianDotP :: Parser String String
  104. stringWithoutMedianDotP = takeWhile (\c -> c /= codePointFromChar '·' && c /= codePointFromChar '•')
  105. uiElementP :: Parser String UIElement
  106. uiElementP = (try dotSeparatedP') <|> simpleUiElementP' where
  107. dotSeparatedP' = do
  108. subStr <- stringWithoutMedianDotP
  109. _ <- medianDotP
  110. _ <- space
  111. sub2Str <- rest
  112. case runParser subStr simpleUiElementP' of
  113. Right sub -> case runParser sub2Str simpleUiElementP' of
  114. Right sub2 -> pure $ UIDotSeparated sub sub2
  115. Left _ -> fail "not a sub"
  116. Left _ -> fail "not a sub"
  117. simpleUiElementP' = (try durationP') <|> (try timeSpanP') <|> stringP'
  118. durationP' = UIDuration <$> durationP
  119. timeSpanP' = UITimeSpan <$> timeSpanP
  120. stringP' = UIPlainText <$> rest