module Parsing.Text (plaintext) where
import Data.Maybe
import Text.Parsec
import Parsing.State
import Parsing.Utils
specials = "*`<>[]|\\"
specialStrings = ["^[", "!["]
firstCharSpecials = " \t#~+\n" ++ specials
nonSpecial :: String -> Parser Char
nonSpecial blacklist = do
escape <- suppressErr (optionMaybe $ char '\\')
if isJust escape
then do
optional $ char '\n'
anyChar
else do
maybeSpecialStrings <- mapM (\s -> suppressErr $ optionMaybe $ lookAhead $ try $ string s) specialStrings
let specialStringsFound = catMaybes maybeSpecialStrings
if length specialStringsFound > 0
then fail $ "special string sequence \"" ++ head specialStringsFound ++ "\""
else noneOf blacklist
nonSpecials :: Parser String
nonSpecials = do
state <- getState
str <- if prevCharIsNewline state
then do
s <- skipPrefix state
if null s
then do
c <- nonSpecial firstCharSpecials
return [c]
else return s
else do
s <- many $ nonSpecial ('\n' : specials)
c <- suppressErr (optionMaybe $ char '\n')
if isJust c
then return (s ++ "\n")
else if null s
then fail ""
else return s
putState $ state {prevCharIsNewline=(last str == '\n')}
return str
plaintext :: Parser String
plaintext = fmap concat $ many1 nonSpecials