module Text.ParserCombinators.HuttonMeijerWallace
(
Parser(..)
, item, eof, papply, papply'
, (+++), tok, nottok, many, many1
, sepby, sepby1, chainl, chainl1, chainr, chainr1, ops, bracket
, toEOF
, elserror
, stupd, stquery, stget
, reparse
) where
import Data.Char
import Control.Monad
infixr 5 +++
type ParseResult s t e a = Either e [(a,s,[Either e t])]
newtype Parser s t e a = P ( s -> [Either e t] -> ParseResult s t e a )
instance Functor (Parser s t e) where
fmap f (P p) = P (\st inp -> case p st inp of
Right res -> Right [(f v, s, out) | (v,s,out) <- res]
Left err -> Left err
)
instance Monad (Parser s t e) where
return v = P (\st inp -> Right [(v,st,inp)])
(P p) >>= f = P (\st inp -> case p st inp of
Right res -> foldr joinresults (Right [])
[ papply' (f v) s out | (v,s,out) <- res ]
Left err -> Left err
)
fail err = P (\st inp -> Right [])
instance MonadPlus (Parser s t e) where
mzero = P (\st inp -> Right [])
(P p) `mplus` (P q) = P (\st inp -> joinresults (p st inp) (q st inp))
joinresults :: ParseResult s t e a -> ParseResult s t e a -> ParseResult s t e a
joinresults (Left p) q = Left p
joinresults (Right []) q = q
joinresults (Right p) q = Right (p++ case q of Left _ -> []
Right r -> r)
item :: Parser s t e t
item = P (\st inp -> case inp of
[] -> Right []
(Left e: _) -> Left e
(Right x: xs) -> Right [(x,st,xs)]
)
eof :: Show p => Parser s (p,t) String ()
eof = P (\st inp -> case inp of
[] -> Right [((),st,[])]
(Left e:_) -> Left e
(Right (p,_):_) -> Left ("End of input expected at "
++show p++"\n but found text")
)
first :: Parser s t e a -> Parser s t e a
first (P p) = P (\st inp -> case p st inp of
Right (x:xs) -> Right [x]
otherwise -> otherwise
)
papply :: Parser s t String a -> s -> [Either String t]
-> [(a,s,[Either String t])]
papply (P p) st inp = either error id (p st inp)
papply' :: Parser s t e a -> s -> [Either e t]
-> Either e [(a,s,[Either e t])]
papply' (P p) st inp = p st inp
(+++) :: Parser s t e a -> Parser s t e a -> Parser s t e a
p +++ q = first (p `mplus` q)
sat :: (t -> Bool) -> Parser s (p,t) e t
sat p = do {(_,x) <- item; if p x then return x else mzero}
tok :: Eq t => t -> Parser s (p,t) e t
tok t = do {(_,x) <- item; if x==t then return t else mzero}
nottok :: Eq t => [t] -> Parser s (p,t) e t
nottok ts = do {(_,x) <- item; if x `notElem` ts then return x
else mzero}
many :: Parser s t e a -> Parser s t e [a]
many p = many1 p +++ return []
many1 :: Parser s t e a -> Parser s t e [a]
many1 p = do {x <- p; xs <- many p; return (x:xs)}
sepby :: Parser s t e a -> Parser s t e b -> Parser s t e [a]
p `sepby` sep = (p `sepby1` sep) +++ return []
sepby1 :: Parser s t e a -> Parser s t e b -> Parser s t e [a]
p `sepby1` sep = do {x <- p; xs <- many (do {sep; p}); return (x:xs)}
chainl :: Parser s t e a -> Parser s t e (a->a->a) -> a
-> Parser s t e a
chainl p op v = (p `chainl1` op) +++ return v
chainl1 :: Parser s t e a -> Parser s t e (a->a->a) -> Parser s t e a
p `chainl1` op = do {x <- p; rest x}
where
rest x = do {f <- op; y <- p; rest (f x y)}
+++ return x
chainr :: Parser s t e a -> Parser s t e (a->a->a) -> a
-> Parser s t e a
chainr p op v = (p `chainr1` op) +++ return v
chainr1 :: Parser s t e a -> Parser s t e (a->a->a) -> Parser s t e a
p `chainr1` op = do {x <- p; rest x}
where
rest x = do { f <- op
; y <- p `chainr1` op
; return (f x y)
}
+++ return x
ops :: [(Parser s t e a, b)] -> Parser s t e b
ops xs = foldr1 (+++) [do {p; return op} | (p,op) <- xs]
bracket :: (Show p,Show t) =>
Parser s (p,t) e a -> Parser s (p,t) e b ->
Parser s (p,t) e c -> Parser s (p,t) e b
bracket open p close = do { open
; x <- p
; close
; return x
}
toEOF :: Show p =>
Parser s (p,t) String a -> Parser s (p,t) String a
toEOF p = do { x <- p; eof; return x }
parseerror :: (Show p,Show t) => String -> Parser s (p,t) String a
parseerror err = P (\st inp ->
case inp of
[] -> Left "Parse error: unexpected EOF\n"
(Left e:_) -> Left ("Lexical error: "++e)
(Right (p,t):_) ->
Left ("Parse error: in "++show p++"\n "
++err++"\n "++"Found "++show t)
)
elserror :: (Show p,Show t) => Parser s (p,t) String a -> String
-> Parser s (p,t) String a
p `elserror` s = p +++ parseerror s
stupd :: (s->s) -> Parser s t e ()
stupd f = P (\st inp->
Right [((), f st, inp)])
stquery :: (s->a) -> Parser s t e a
stquery f = P (\st inp-> Right [(f st, st, inp)])
stget :: Parser s t e s
stget = P (\st inp-> Right [(st, st, inp)])
reparse :: [Either e t] -> Parser s t e ()
reparse ts = P (\st inp-> Right [((), st, ts++inp)])