module Text.HPaco.Readers.Common
( module Text.Parsec.Combinator
, module Text.Parsec.Char
, module Text.Parsec.Prim
, module Text.Parsec.String
, Parser
, ss, ss_
, discard
, manySepBy
, braces
, identifier
, path
, anyQuotedString, singleQuotedString, doubleQuotedString
, assertStartOfInput, assertStartOfLine
, assertEndOfWord, assertEndOfOperator
, keyword, operatorKeyword
)
where
import Text.Parsec.Char
import Text.Parsec.Combinator
import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn, sourceName)
import Text.Parsec.Prim
import Text.Parsec.String hiding (Parser)
import Control.Monad.IO.Class
import System.IO.Strict
type Parser s a = ParsecT String s IO a
ss :: a -> Parser s a
ss a = skipMany space >> return a
ss_ :: Parser s ()
ss_ = ss ()
braces :: Parser s a -> Parser s a
braces inner = do
char '{'
ss_
v <- inner
ss_
char '}'
return v
identifier :: Parser s String
identifier = do
x <- letter <|> char '_'
xs <- many $ letter <|> digit <|> char '_'
return $ x:xs
anyQuotedString = singleQuotedString <|> doubleQuotedString
singleQuotedString = quotedString '\''
doubleQuotedString = quotedString '"'
quotedString qc = do
char qc
str <- many $ quotedStringChar qc
char qc
return str
quotedStringChar qc =
try escapedChar
<|> noneOf [qc]
escapedChar :: Parser s Char
escapedChar = do
char '\\'
c2 <- anyChar
return $ case c2 of
'n' -> '\n'
'r' -> '\r'
'b' -> '\b'
't' -> '\t'
otherwise -> c2
discard :: Parser s a -> Parser s ()
discard p = p >> return ()
manySepBy :: Parser s a -> Parser s b -> Parser s [a]
manySepBy elem sep = do
h <- try elem
t <- many (try $ sep >> elem)
return $ h:t
assertStartOfInput :: Parser s ()
assertStartOfInput = do
pos <- getPosition
if sourceLine pos == 1 && sourceColumn pos == 1
then return ()
else unexpected "start of input"
assertStartOfLine :: Parser s ()
assertStartOfLine = do
pos <- getPosition
if sourceColumn pos == 1
then return ()
else unexpected "start of line"
path :: Parser s String
path = many1 $ try $ noneOf " \t\r\n%()"
keyword :: String -> Parser s ()
keyword str = do
string str
assertEndOfWord
assertEndOfWord :: Parser s ()
assertEndOfWord = notFollowedBy $ letter <|> digit <|> char '_'
operatorKeyword :: String -> Parser s ()
operatorKeyword str = do
string str
assertEndOfOperator
assertEndOfOperator :: Parser s ()
assertEndOfOperator = notFollowedBy $ oneOf "!@#$%^&*_-+=;:,./?\\|<>~`"