neat-interpolation-0.2.3: library/NeatInterpolation/Parsing.hs
module NeatInterpolation.Parsing where
import BasePrelude hiding (try, (<|>), many)
import Text.Parsec hiding (Line)
data Line =
Line {lineIndent :: Int, lineContents :: [LineContent]}
deriving (Show)
data LineContent =
LineContentText [Char] |
LineContentIdentifier [Char]
deriving (Show)
parseLines :: [Char] -> Either ParseError [Line]
parseLines = parse lines "NeatInterpolation.Parsing.parseLines"
where
lines = sepBy line newline <* eof
line = Line <$> countIndent <*> many content
countIndent = fmap length $ try $ lookAhead $ many $ char ' '
content = try identifier <|> contentText
identifier = fmap LineContentIdentifier $
char '$' *> (try identifier' <|> between (char '{') (char '}') identifier')
identifier' = many1 (alphaNum <|> char '\'' <|> char '_')
contentText = do
text <- manyTill anyChar end
if null text
then fail "Empty text"
else return $ LineContentText $ text
where
end =
(void $ try $ lookAhead identifier) <|>
(void $ try $ lookAhead newline) <|>
eof