module Text.LParse.Prebuilt where
import Control.Applicative
import Control.DoubleContinuations
import Control.Monad
import Data.Char
import Text.LParse.Parser
import qualified Text.LParse.TokenStream as T
import Text.LParse.TokenStream (TokenStream,top,rest,nil,cons)
noop :: Parser r t ()
noop = return ()
peek :: (TokenStream s) => (t -> Bool) -> String -> Parser r (s t) ()
peek c = cParse (c . top) noop
eoi :: Parser r [t] ()
eoi = cParse null noop "Input not fully consumed"
discard :: Parser r [t] ()
discard = void full
consume :: (Eq t, Show (s t), TokenStream s) => s t -> Parser r (s t) ()
consume pre = cParse ((&&) <$> (and . T.zipWith (==) pre) <*> ((>= length pre) . length)) (pParse (T.drop (length pre)) noop) ("Expected " ++ show pre)
consumeReturn :: (Eq t, Show (s t), TokenStream s) => s t -> a -> Parser r (s t) a
consumeReturn t a = consume t >> return a
consumeSingle :: (Eq t, Show t, TokenStream s) => t -> Parser r (s t) ()
consumeSingle t = cParse (\s -> not (null s) && top s == t) (pParse rest noop) ("Expected " ++ show t)
consumeSReturn :: (Eq t, Show t, TokenStream s) => t -> a -> Parser r (s t) a
consumeSReturn t a = consumeSingle t >> return a
tokenReturn :: (TokenStream s) => Parser r (s a) a
tokenReturn = tokenParse id
full :: Parser r [t] [t]
full = many tokenReturn
tokenParse :: (TokenStream s) => (t -> a) -> Parser r (s t) a
tokenParse f = Parser (\s -> DCont (\btr etr -> if null s then etr "Unexpected EOI" else btr (f $ top s,rest s)))
success :: (t -> (a,t)) -> Parser r t a
success = Parser . (return .)
digit :: Parser r String Integer
digit = read . return <$> cParse (\s -> not (null s) && isDigit (head s)) tokenReturn "Expected digit"
letter :: Parser r String Char
letter = cParse (\s -> not (null s) && isLetter (head s)) tokenReturn "Expected letter"
word :: Parser r String String
word = some letter
integer :: Parser r String Integer
integer = foldl (\x y -> x*10+y) 0 <$> some digit
sInteger :: Parser r String Integer
sInteger = (\m i -> case m of (Just _) -> -i; Nothing -> i) <$> try (consumeSingle '-') <*> integer
bDigit :: Integer -> Parser r Integer Integer
bDigit b = cParse (> 0) (success (\i -> (i `mod` b,i `div` b))) "Empty number!"
bDigits :: Integer -> Parser r Integer [Integer]
bDigits b = many $ bDigit b
try :: Parser r t a -> Parser r t (Maybe a)
try p = (Just <$> p) <|> return Nothing
surround :: (Eq t, Show t, TokenStream s) => [t] -> Parser r (s t) a -> Parser r (s t) a
surround [l,r] p = consumeSingle l >> p << consumeSingle r
cParse :: (t -> Bool) -> Parser r t a -> String -> Parser r t a
cParse c p err = Parser (\s -> if c s then pFunc p s else throw err)
nParse :: (TokenStream s, Eq (s t)) => (t -> Bool) -> Parser r (s t) a -> String -> Parser r (s t) a
nParse c = cParse (\s -> nil /= s && c (top s))
pParse :: (t -> t) -> Parser r t a -> Parser r t a
pParse f p = Parser (pFunc p . f)
skip :: (Eq t, TokenStream s) => [t] -> Parser r (s t) a -> Parser r (s t) a
skip s = skipBy (not . (`elem` s))
skipBy :: (TokenStream s) => (t -> Bool) -> Parser r (s t) a -> Parser r (s t) a
skipBy f = pParse (T.filter f)
skipWhitespace :: Parser r String a -> Parser r String a
skipWhitespace = skipBy (not . isSpace)
replace :: (TokenStream s) => (t -> t) -> Parser r (s t) a -> Parser r (s t) a
replace f p = Parser (pFunc p . (\x -> f (top x) `cons` rest x))
(<<) :: (Monad m) => m a -> m b -> m a
a << b = a >>= ((b >>) . return)
sepSome :: Parser r t () -> Parser r t a -> Parser r t [a]
sepSome sep p = ((:) <$> p <*> many (sep >> p)) <|> fmap return p
sepMany :: Parser r t () -> Parser r t a -> Parser r t [a]
sepMany sep p = sepSome sep p <|> return []