module Parsing.TextUtils where

import Data.Maybe
import Text.Parsec

import Parsing.State
import Parsing.Utils

-- Parse a single character and update parsing state accordingly.
char' :: Char -> Parser Char
char' c = if c == '\n'
    then do
        newline <|> (eof >> return '\n')
        modifyState $ \s -> s {prevCharIsNewline=True}
        return '\n'
    else do
        char c
        modifyState $ \s -> s {prevCharIsNewline=False}
        return c

-- Parse a string of characters and update parsing state accordingly.
string' :: String -> Parser String
string' = mapM char'

-- Parse a string of characters not in [blacklist], unless they are escaped,
-- and update state like [string'].
escapableNoneOf :: String -> Parser Char
escapableNoneOf blacklist = do
    escape <- suppressErr (optionMaybe $ char '\\')
    c <- if isJust escape
        then anyChar
        else noneOf blacklist
    modifyState $ \s -> s {prevCharIsNewline=(c == '\n')}
    return c

-- Like [betweenWithErrors], but updates state when parsing the start and end strings.
betweenWithErrors' :: String -> String -> String -> Parser a -> Parser a
betweenWithErrors' open close name = between
    (try (string' open) <?> "\"" ++ open ++ "\" (" ++ name ++ ")")
    (try (string' close) <?> "closing \"" ++ close ++ "\" (" ++ name ++ ")")