12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- {-# LANGUAGE OverloadedStrings #-}
- module Parser where
- import Data.Char as Char
- import qualified Data.Text as Text
- import Types
- data LineType
- = TableDecl Int Text.Text
- | TableEntry Range Result
- deriving (Eq, Show)
- indentAmount :: Text.Text -> Int
- indentAmount = Text.length . Text.takeWhile Char.isSpace
- parseRange :: Text.Text -> Range
- parseRange t
- | Text.all Char.isNumber (Text.strip t) =
- let n = read (Text.unpack t) in Range n n
- | otherwise =
- let (x, y) = Text.breakOn "-" (Text.strip t)
- n = read (Text.unpack x)
- m = read (Text.unpack (Text.tail y))
- in Range n m
- parseFragments :: Text.Text -> [Fragment]
- parseFragments t =
- let (frag, roll) = Text.breakOn "@{" t
- in case roll of
- "" -> [FragText frag]
- _ ->
- let (name, rest) = Text.breakOn "}" (Text.drop 2 roll)
- in FragText frag : FragRoll name : parseFragments (Text.tail rest)
- parseLines :: [Text.Text] -> [LineType]
- parseLines = go
- where
- go [] = []
- go (t:ts)
- | Text.all Char.isSpace t = go ts
- | Text.any (== ':') t =
- let (rangeTxt, message) = Text.breakOn ":" t
- range = parseRange rangeTxt
- msg = parseFragments (Text.tail message)
- in TableEntry range (Result msg) : go ts
- | otherwise =
- TableDecl (indentAmount t) (Text.strip t) : go ts
- parseTable :: Text.Text -> [Table]
- parseTable = parseTop [] . parseLines . Text.lines
- where
- parseTop _ [] = []
- parseTop ctx (TableDecl n name:xs) =
- parseTop ((n, name) : [ c | c <- ctx, fst c < n]) xs
- parseTop ctx (TableEntry r m:xs) =
- let (table, rest) = gatherEntries ctx xs [(r, m)]
- in table : parseTop ctx rest
- gatherEntries ctx (TableEntry r m:xs) es =
- gatherEntries ctx xs ((r, m) : es)
- gatherEntries ctx rs es =
- let name = Text.intercalate "/" (reverse (map snd ctx))
- in (Table name (reverse es), rs)
|