Parser.hs 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Parser where
  3. import Data.Char as Char
  4. import qualified Data.Text as Text
  5. import Types
  6. data LineType
  7. = TableDecl Int Text.Text
  8. | TableEntry Range Result
  9. deriving (Eq, Show)
  10. indentAmount :: Text.Text -> Int
  11. indentAmount = Text.length . Text.takeWhile Char.isSpace
  12. parseRange :: Text.Text -> Range
  13. parseRange t
  14. | Text.all Char.isNumber (Text.strip t) =
  15. let n = read (Text.unpack t) in Range n n
  16. | otherwise =
  17. let (x, y) = Text.breakOn "-" (Text.strip t)
  18. n = read (Text.unpack x)
  19. m = read (Text.unpack (Text.tail y))
  20. in Range n m
  21. parseResult :: Text.Text -> Result
  22. parseResult t
  23. | "@" `Text.isPrefixOf` Text.strip t =
  24. ResultRoll (Text.tail (Text.strip t))
  25. | otherwise =
  26. ResultText (Text.strip t)
  27. parseLines :: [Text.Text] -> [LineType]
  28. parseLines = go
  29. where
  30. go [] = []
  31. go (t:ts)
  32. | Text.all Char.isSpace t = go ts
  33. | Text.any (== ':') t =
  34. let (rangeTxt, message) = Text.breakOn ":" t
  35. range = parseRange rangeTxt
  36. msg = parseResult (Text.tail message)
  37. in TableEntry range msg : go ts
  38. | otherwise =
  39. TableDecl (indentAmount t) (Text.strip t) : go ts
  40. parseTable :: Text.Text -> [Table]
  41. parseTable = parseTop [] . parseLines . Text.lines
  42. where
  43. parseTop _ [] = []
  44. parseTop ctx (TableDecl n name:xs) =
  45. parseTop ((n, name) : [ c | c <- ctx, fst c < n]) xs
  46. parseTop ctx (TableEntry r m:xs) =
  47. let (table, rest) = gatherEntries ctx xs [(r, m)]
  48. in table : parseTop ctx rest
  49. gatherEntries ctx (TableEntry r m:xs) es =
  50. gatherEntries ctx xs ((r, m) : es)
  51. gatherEntries ctx rs es =
  52. let name = Text.intercalate "/" (reverse (map snd ctx))
  53. in (Table name (reverse es), rs)