module SMR.Source.Parsec where
import qualified SMR.Data.Bag as Bag
import SMR.Data.Bag (Bag)
data Parser t e a
= Parser ([t] -> ParseResult t e a)
data ParseResult t e a
= ParseSkip
(Bag (Blocker t e))
| ParseReturn
(Bag (Blocker t e))
a
| ParseFailure
(Bag (Blocker t e))
| ParseSuccess
a
[t]
deriving Show
data Blocker t e
= Blocker
{ blockerTokens :: [t]
, blockerExpected :: e
}
deriving Show
parse :: Parser t e a -> [t] -> ParseResult t e a
parse (Parser p) ts = p ts
instance Functor (Parser t e) where
fmap f parserA
= Parser $ \ts0
-> case parse parserA ts0 of
ParseSkip bs1 -> ParseSkip bs1
ParseReturn bs1 x -> ParseReturn bs1 (f x)
ParseFailure bs1 -> ParseFailure bs1
ParseSuccess a ts1 -> ParseSuccess (f a) ts1
instance Applicative (Parser t e) where
pure x
= Parser $ \_
-> ParseReturn Bag.nil x
(<*>) parserF parserA
= Parser $ \ts0
-> case parse parserF ts0 of
ParseSkip es1
-> ParseSkip es1
ParseFailure bs1
-> ParseFailure bs1
ParseReturn es1 f
-> case parse parserA ts0 of
ParseSkip es2 -> ParseSkip (Bag.union es1 es2)
ParseReturn es2 x -> ParseReturn (Bag.union es1 es2) (f x)
ParseFailure bs2 -> ParseFailure (Bag.union es1 bs2)
ParseSuccess x ts2 -> ParseSuccess (f x) ts2
ParseSuccess f ts1
-> case parse parserA ts1 of
ParseSkip bs2 -> ParseFailure bs2
ParseReturn _ x -> ParseSuccess (f x) ts1
ParseFailure bs2 -> ParseFailure bs2
ParseSuccess x ts2 -> ParseSuccess (f x) ts2
instance Monad (Parser t e) where
return x
= Parser $ \_
-> ParseReturn Bag.nil x
(>>=) parserA mkParserB
= Parser $ \ts0
-> case parse parserA ts0 of
ParseSkip bs1
-> ParseSkip bs1
ParseFailure bs1
-> ParseFailure bs1
ParseReturn _ xa
-> parse (mkParserB xa) ts0
ParseSuccess xa ts1
-> case parse (mkParserB xa) ts1 of
ParseSkip bs2 -> ParseFailure bs2
ParseReturn _ xb -> ParseSuccess xb ts1
ParseFailure bs2 -> ParseFailure bs2
ParseSuccess xb ts2 -> ParseSuccess xb ts2
fail :: Parser t e a
fail
= Parser $ \_
-> ParseFailure Bag.nil
expected :: e -> Parser t e a
expected xe
= Parser $ \ts
-> ParseFailure (Bag.singleton (Blocker ts xe))
commit :: Parser t e a -> Parser t e a
commit parserA
= Parser $ \ts0
-> case parse parserA ts0 of
ParseSkip bs1 -> ParseFailure bs1
ParseReturn bs1 _ -> ParseFailure bs1
ParseFailure bs1 -> ParseFailure bs1
ParseSuccess xb xs2 -> ParseSuccess xb xs2
enter :: (Bag (Blocker t e) -> e) -> Parser t e a -> Parser t e a
enter mk parserA
= Parser $ \ts0
-> case parse parserA ts0 of
ParseSkip bs1
-> ParseSkip (Bag.singleton (Blocker ts0 (mk bs1)))
ParseReturn bs1 x
-> ParseReturn (Bag.singleton (Blocker ts0 (mk bs1))) x
ParseFailure bs1
-> ParseFailure (Bag.singleton (Blocker ts0 (mk bs1)))
ParseSuccess xb ts2
-> ParseSuccess xb ts2
enterOn :: Parser t e a
-> (a -> Bag (Blocker t e) -> e)
-> (a -> Parser t e b)
-> Parser t e b
enterOn parserA mk mkParserB
= Parser $ \ts0
-> case parse parserA ts0 of
ParseSkip bs0
-> ParseSkip bs0
ParseFailure bs1
-> ParseFailure bs1
ParseReturn _ xa
-> case parse (mkParserB xa) ts0 of
ParseSkip bs2
-> ParseSkip (Bag.singleton (Blocker ts0 (mk xa bs2)))
ParseReturn bs2 xb
-> ParseReturn (Bag.singleton (Blocker ts0 (mk xa bs2))) xb
ParseFailure bs2
-> ParseFailure (Bag.singleton (Blocker ts0 (mk xa bs2)))
ParseSuccess xb ts2
-> ParseSuccess xb ts2
ParseSuccess xa ts1
-> case parse (mkParserB xa) ts1 of
ParseSkip bs2
-> ParseSkip (Bag.singleton (Blocker ts0 (mk xa bs2)))
ParseReturn bs2 xb
-> ParseReturn (Bag.singleton (Blocker ts0 (mk xa bs2))) xb
ParseFailure bs2
-> ParseFailure (Bag.singleton (Blocker ts0 (mk xa bs2)))
ParseSuccess xb ts2
-> ParseSuccess xb ts2
peek :: Parser t e t
peek
= Parser $ \ts
-> case ts of
[] -> ParseFailure Bag.nil
t : _ -> ParseReturn Bag.nil t
item :: e -> Parser t e t
item xe
= Parser $ \ts
-> case ts of
[] -> ParseSkip (Bag.singleton (Blocker ts xe))
t : ts' -> ParseSuccess t ts'
satisfies :: e -> (t -> Bool) -> Parser t e t
satisfies xe p
= Parser $ \ts
-> case ts of
[] -> ParseSkip (Bag.singleton (Blocker ts xe))
t : ts'
| p t -> ParseSuccess t ts'
| otherwise -> ParseSkip (Bag.singleton (Blocker ts xe))
from :: e -> (t -> Maybe a) -> Parser t e a
from xe accept
= Parser $ \ts
-> case ts of
[] -> ParseSkip (Bag.singleton (Blocker ts xe))
t : ts'
-> case accept t of
Just x -> ParseSuccess x ts'
Nothing -> ParseSkip (Bag.singleton (Blocker ts xe))
alt :: Parser t e a -> Parser t e a -> Parser t e a
alt parserA parserB
= alts (parserA : parserB : [])
alts :: [Parser t e a] -> Parser t e a
alts parsers
= Parser $ \ts0
-> go ts0 (False, Nothing) (Bag.nil, Bag.nil) parsers
where
go _ (False, Nothing) (bsSkip, _bsFail) []
= ParseSkip bsSkip
go _ (False, (Just x)) (bsSkip, _bsFail) []
= ParseReturn bsSkip x
go _ (True, _) (_bsSkip, bsFail) []
= ParseFailure bsFail
go ts0 (failed, mx) (bsSkip, bsFail) (p : ps)
= case parse p ts0 of
ParseSkip bs1
-> go ts0 (failed, mx) (Bag.union bsSkip bs1, bsFail) ps
ParseFailure bs1
-> go ts0 (True, mx) (bsSkip, Bag.union bsFail bs1) ps
ParseReturn bs1 x
-> go ts0 (failed, Just x) (Bag.union bsSkip bs1, bsFail) ps
ParseSuccess x ts1
-> ParseSuccess x ts1
some :: Parser t e a -> Parser t e [a]
some parserA
= alt (do
x <- parserA
xs <- some parserA
return $ x : xs)
(return [])
many :: Parser t e a -> Parser t e [a]
many parserA
= do x <- parserA
xs <- some parserA
return $ x : xs
sepBy :: Parser t e a -> Parser t e s -> Parser t e [a]
sepBy parserA parserS
= alt (sepBy1 parserA parserS)
(return [])
sepBy1 :: Parser t e a -> Parser t e s -> Parser t e [a]
sepBy1 parserA parserS
= do x <- parserA
alt
(do _s <- parserS
xs <- sepBy1 parserA parserS
return $ x : xs)
(do return $ x : [])
withDelims :: Parser t e a -> Parser t e (t, a, t)
withDelims p
= do kStart <- peek
x <- p
kEnd <- peek
return (kStart, x, kEnd)