gdritter repos ndbl / 875c1e8
Cleaned up parts of parser Getty Ritter 10 years ago
1 changed file(s) with 29 addition(s) and 31 deletion(s). Collapse all Expand all
1313
1414 type Pair = (Text, Text)
1515
16
17
1816 isSep :: Char -> Bool
1917 isSep ' ' = True
2018 isSep '\t' = True
2321 isSep '=' = True
2422 isSep _ = False
2523
24 -- | Skips any horizontal (non-new-line) spaces
2625 hSpace :: Parser ()
2726 hSpace = skipWhile isHorizontalSpace
2827
29 pString :: Parser Text
30 pString = string "\"" *> (T.pack <$> sBody)
28 -- | Parses a quotedd string
29 pQString :: Parser Text
30 pQString = string "\"" *> (T.pack <$> sBody)
3131 where sBody = do
3232 c <- anyChar
3333 case c of
3535 '"' -> return []
3636 _ -> (c:) <$> sBody
3737
38 -- | Parse a word of any length
3839 pWord :: Parser Text
3940 pWord = takeWhile (not . isSep)
4041
42 -- | Parse a word of at least length one
4143 pWord1 :: Parser Text
4244 pWord1 = takeWhile1 (not . isSep)
4345
46 -- | Parse a key-value pair
4447 pPair :: Parser Pair
45 pPair = (,) <$> pWord1 <*. "=" <*> (pString <|> pWord)
48 pPair = (,) <$> pWord1 <*. "=" <*> (pQString <|> pWord)
4649
50 -- | Directions passed back from the skipping parsers---whether
51 -- to continue parsing the current block, start a new block,
52 -- or stop entirely.
4753 data NewBlock
4854 = StartNewBlock
4955 | ContinueBlock
5056 | StopParsing
5157 deriving (Eq,Show)
5258
53 sNextMSet :: Parser NewBlock
54 sNextMSet = do
55 hSpace
56 n <- peekChar
57 go n
58 where go (Just '\n') = do
59 _ <- anyChar
60 n <- peekChar
61 go' n
62 go (Just '#') = do
63 skipWhile (not . (== '\n'))
64 sNextMSet
65 go (Just _) = return ContinueBlock
66 go Nothing = return StopParsing
67 go' (Just '\n') = do
68 _ <- anyChar
69 n <- peekChar
70 go' n
71 go' (Just '#') = do
72 skipWhile (not . (== '\n'))
73 n <- peekChar
74 go' n
75 go' (Just c) | isSpace c = sNextMSet
76 | otherwise = return StartNewBlock
77 go' Nothing = return StopParsing
59 comment :: Parser ()
60 comment = char '#' >> skipWhile (not . (== '\n'))
61
62 -- | Skips to the next pair (or end of input) and returns whether to parse
63 -- the next pair as part of the same group, the next group, or whether
64 -- it's reached the end.
65 sSkipToNext :: Bool -> Parser NewBlock
66 sSkipToNext False = hSpace >> peekChar >>= go
67 where go (Just '\n') = anyChar >> sSkipToNext True
68 go (Just '\r') = anyChar >> sSkipToNext True
69 go (Just '#') = comment >> sSkipToNext False
70 go (Just _) = return ContinueBlock
71 go Nothing = return StopParsing
72 sSkipToNext True = peekChar >>= go
73 where go (Just c) | isSpace c = anyChar >> sSkipToNext False
74 | otherwise = return StartNewBlock
75 go Nothing = return StopParsing
7876
7977 pBlock :: Parser (NewBlock, [Pair])
8078 pBlock = do
8179 p <- pPair
82 b <- sNextMSet
80 b <- sSkipToNext False
8381 case b of
8482 StartNewBlock -> return (StartNewBlock, [p])
8583 StopParsing -> return (StopParsing, [p])