module Text.ParserCombinators.UU.Core
(
IsParser,
ExtAlternative (..),
Eof (..),
IsLocationUpdatedBy (..),
StoresErrors (..),
HasPosition (..),
P (..),
Steps (..),
Cost,
Progress,
Nat (..),
Strings,
micro,
amb,
pErrors,
pPos,
pState,
pEnd,
pSwitch,
pSymExt,
parse, parse_h,
getZeroP,
getOneP,
addLength,
eval,
module Control.Applicative,
module Control.Monad
) where
import Control.Applicative
import Control.Monad
import Data.Char
import Debug.Trace
import Prelude hiding ((.))
import Data.Maybe
f . g = \x -> f ( g x)
class (Alternative p, Applicative p, ExtAlternative p) => IsParser p
instance MonadPlus (P st) where
mzero = empty
mplus = (<|>)
class (Alternative p) => ExtAlternative p where
(<<|>) :: p a -> p a -> p a
(<?>) :: p a -> String -> p a
must_be_non_empty :: String -> p a -> c -> c
must_be_non_empties :: String -> p a -> p b -> c -> c
opt :: p a -> a -> p a
opt p v = must_be_non_empty "opt" p (p <<|> pure v)
infix 2 <?>
infixl 3 <<|>
infixl 2 `opt`
class Eof state where
eof :: state -> Bool
deleteAtEnd :: state -> Maybe (Cost, state)
class Show loc => loc `IsLocationUpdatedBy` str where
advance :: loc
-> str
-> loc
class state `StoresErrors` error | state -> error where
getErrors :: state -> ([error], state)
class state `HasPosition` pos | state -> pos where
getPos :: state -> pos
data T st a = T (forall r . (a -> st -> Steps r) -> st -> Steps r )
(forall r . ( st -> Steps r) -> st -> Steps (a, r) )
(forall r . ( st -> Steps r) -> st -> Steps r )
instance Functor (T st) where
fmap f (T ph pf pr) = T ( \ k -> ph ( k .f ))
( \ k -> apply2fst f . pf k)
pr
f <$ (T _ _ pr) = T ( pr . ($f))
( \ k st -> push f ( pr k st))
pr
instance Applicative (T state) where
T ph pf pr <*> ~(T qh qf qr) = T ( \ k -> ph (\ pr -> qh (\ qr -> k (pr qr))))
((apply .) . (pf .qf))
( pr . qr)
T ph pf pr <* ~(T _ _ qr) = T ( ph. (qr.)) (pf. qr) (pr . qr)
T _ _ pr *> ~(T qh qf qr ) = T ( pr . qh ) (pr. qf) (pr . qr)
pure a = T ($a) ((push a).) id
instance Alternative (T state) where
T ph pf pr <|> T qh qf qr = T (\ k inp -> ph k inp `best` qh k inp)
(\ k inp -> pf k inp `best` qf k inp)
(\ k inp -> pr k inp `best` qr k inp)
empty = T ( \ k inp -> noAlts) ( \ k inp -> noAlts) ( \ k inp -> noAlts)
data P st a = P (T st a)
(Maybe (T st a))
(Maybe a)
Nat
instance Show (P st a) where
show (P _ nt e n) = "P _ " ++ maybe "Nothing" (const "(Just _)") nt ++ maybe "Nothing" (const "(Just _)") e ++ " (" ++ show n ++ ") "
getOneP :: P a b -> Maybe (P a b)
getOneP (P _ Nothing _ l) = Nothing
getOneP (P _ onep ep l) = Just( mkParser onep Nothing (getLength l))
getZeroP :: P t a -> Maybe a
getZeroP (P _ _ z _) = z
mkParser :: Maybe (T st a) -> Maybe a -> Nat -> P st a
mkParser np ne l = P (mkParser' np ne) np ne l
where mkParser' np@(Just nt) ne@Nothing = nt
mkParser' np@Nothing ne@(Just a) = pure a
mkParser' np@(Just nt) ne@(Just a) = nt <|> pure a
mkParser' np@(Nothing) ne@(Nothing) = empty
combine :: (Alternative f) => Maybe t1 -> Maybe t2 -> t -> Maybe t3
-> (t1 -> t -> f a) -> (t2 -> t3 -> f a) -> Maybe (f a)
combine Nothing Nothing _ _ _ _ = Nothing
combine (Just p) Nothing aq _ op1 op2 = Just (p `op1` aq)
combine (Just p) (Just v) aq nq op1 op2 = case nq of
Just nnq -> Just (p `op1` aq <|> v `op2` nnq)
Nothing -> Just (p `op1` aq )
combine Nothing (Just v) _ nq _ op2 = case nq of
Just nnq -> Just (v `op2` nnq)
Nothing -> Nothing
instance Functor (P state) where
fmap f (P ap np me l) = P (fmap f ap) (fmap (fmap f) np) (f <$> me) l
f <$ (P ap np me l) = P (f <$ ap) (fmap (f <$) np) (f <$ me) l
instance Applicative (P state) where
P ap np pe pl <*> ~(P aq nq qe ql) = trace' "<*>" (mkParser (combine np pe aq nq (<*>) (<$>)) (pe <*> qe) (nat_add pl ql))
P ap np pe pl <* ~(P aq nq qe ql) = trace' "<* " (mkParser (combine np pe aq nq (<*) (<$)) (pe <* qe ) (nat_add pl ql))
P ap np pe pl *> ~(P aq nq qe ql) = trace' " *>" (mkParser (combine np pe aq nq (*>) (flip const)) (pe *> qe ) (nat_add pl ql))
pure a = trace' "pure" (mkParser Nothing (Just a ) (Zero Infinite))
instance Alternative (P state) where
P ap np pe pl <|> P aq nq qe ql
= let pl' = maybe pl (const (Zero pl)) pe
ql' = maybe ql (const (Zero ql)) qe
(rl, b) = trace' "calling natMin from <|>" (nat_min pl' ql' 0)
Nothing `alt` q = q
p `alt` Nothing = p
Just p `alt` Just q = Just (p <|>q)
in mkParser ((if b then id else flip) alt np nq) (pe <|> qe) rl
empty = mkParser empty empty Infinite
instance ExtAlternative (P st) where
P ap np pe pl <<|> P aq nq qe ql
= let (rl, b) = nat_min pl ql 0
bestx :: Steps a -> Steps a -> Steps a
bestx = (if b then id else flip) best
choose:: T st a -> T st a -> T st a
choose (T ph pf pr) (T qh qf qr)
= T (\ k st -> let left = norm (ph k st)
in if has_success left then left else left `bestx` qh k st)
(\ k st -> let left = norm (pf k st)
in if has_success left then left else left `bestx` qf k st)
(\ k st -> let left = norm (pr k st)
in if has_success left then left else left `bestx` qr k st)
in P (choose ap aq )
(maybe np (\nqq -> maybe nq (\npp -> return( choose npp nqq)) np) nq)
(pe <|> qe)
rl
P _ np pe pl <?> label = let replaceExpected :: Steps a -> Steps a
replaceExpected (Fail _ c) = (Fail [label] c)
replaceExpected others = others
nnp = case np of Nothing -> Nothing
Just ((T ph pf pr)) -> Just(T ( \ k inp -> replaceExpected (norm ( ph k inp)))
( \ k inp -> replaceExpected (norm ( pf k inp)))
( \ k inp -> replaceExpected (norm ( pr k inp))))
in mkParser nnp pe pl
must_be_non_empty msg p@(P _ _ _ (Zero _)) _
= error ("The combinator " ++ msg ++ " requires that it's argument cannot recognise the empty string\n")
must_be_non_empty _ _ q = q
must_be_non_empties msg (P _ _ _ (Zero _)) (P _ _ _ (Zero _)) _
= error ("The combinator " ++ msg ++ " requires that not both arguments can recognise the empty string\n")
must_be_non_empties _ _ _ q = q
instance IsParser (P st)
instance Monad (P st) where
p@(P ap np pe pl ) >>= a2q =
(P newap newnp newep (nat_add pl Hole))
where (newep, newnp, newap) = case pe of
Nothing -> (Nothing, t, maybe empty id t)
Just a -> let P aq nq eq lq = a2q a
in (eq, combine t nq , t `alt` aq)
Nothing `alt` q = q
Just p `alt` q = p <|> q
t = fmap (\ (T h _ _ ) -> (T ( \k -> h (\ a -> unParser_h (a2q a) k))
( \k -> h (\ a -> unParser_f (a2q a) k))
( \k -> h (\ a -> unParser_r (a2q a) k))) ) np
combine Nothing Nothing = Nothing
combine l@(Just _ ) Nothing = l
combine Nothing r@(Just _ ) = r
combine (Just l) (Just r) = Just (l <|> r)
unParser_h :: P b a -> (a -> b -> Steps r) -> b -> Steps r
unParser_h (P (T h _ _ ) _ _ _ ) = h
unParser_f :: P b a -> (b -> Steps r) -> b -> Steps (a, r)
unParser_f (P (T _ f _ ) _ _ _ ) = f
unParser_r :: P b a -> (b -> Steps r) -> b -> Steps r
unParser_r (P (T _ _ r ) _ _ _ ) = r
return = pure
pSymExt :: (forall a. (token -> state -> Steps a) -> state -> Steps a) -> Nat -> Maybe token -> P state token
pSymExt splitState l e = mkParser (Just t) e l
where t = T ( splitState )
( \ k -> splitState (\ t -> push t . k) )
( \ k -> splitState (\ _ -> k ) )
micro :: P state a -> Int -> P state a
P _ np pe pl `micro` i
= let nnp = fmap (\ (T ph pf pr) -> (T ( \ k st -> ph (\ a st -> Micro i (k a st)) st)
( \ k st -> pf (Micro i .k) st)
( \ k st -> pr (Micro i .k) st))) np
in mkParser nnp pe pl
amb :: P st a -> P st [a]
amb (P _ np pe pl)
= let combinevalues :: Steps [(a,r)] -> Steps ([a],r)
combinevalues lar = Apply (\ lar -> (map fst lar, snd (head lar))) lar
nnp = case np of
Nothing -> Nothing
Just ((T ph pf pr)) -> Just(T ( \k -> removeEnd_h . ph (\ a st' -> End_h ([a], \ as -> k as st') noAlts))
( \k inp -> combinevalues . removeEnd_f $ pf (\st -> End_f [k st] noAlts) inp)
( \k -> removeEnd_h . pr (\ st' -> End_h ([undefined], \ _ -> k st') noAlts)))
nep = (fmap pure pe)
in mkParser nnp nep pl
pErrors :: StoresErrors st error => P st [error]
pErrors = let nnp = Just (T ( \ k inp -> let (errs, inp') = getErrors inp in k errs inp' )
( \ k inp -> let (errs, inp') = getErrors inp in push errs (k inp'))
( \ k inp -> let (errs, inp') = getErrors inp in k inp' ))
in mkParser nnp Nothing (Zero Infinite)
pPos :: HasPosition st pos => P st pos
pPos = let nnp = Just ( T ( \ k inp -> let pos = getPos inp in k pos inp )
( \ k inp -> let pos = getPos inp in push pos (k inp))
( \ k inp -> k inp ))
in mkParser nnp Nothing (Zero Infinite)
pState :: P st st
pState = let nnp = Just ( T ( \ k inp -> k inp inp)
( \ k inp -> push inp (k inp))
($))
in mkParser nnp Nothing (Zero Infinite)
pEnd :: (StoresErrors st error, Eof st) => P st [error]
pEnd = let nnp = Just ( T ( \ k inp -> let deleterest inp = case deleteAtEnd inp of
Nothing -> let (finalerrors, finalstate) = getErrors inp
in k finalerrors finalstate
Just (i, inp') -> Fail [] [const (i, deleterest inp')]
in deleterest inp)
( \ k inp -> let deleterest inp = case deleteAtEnd inp of
Nothing -> let (finalerrors, finalstate) = getErrors inp
in push finalerrors (k finalstate)
Just (i, inp') -> Fail [] [const ((i, deleterest inp'))]
in deleterest inp)
( \ k inp -> let deleterest inp = case deleteAtEnd inp of
Nothing -> let (finalerrors, finalstate) = getErrors inp
in (k finalstate)
Just (i, inp') -> Fail [] [const (i, deleterest inp')]
in deleterest inp))
in mkParser nnp Nothing (Zero Infinite)
pSwitch :: (st1 -> (st2, st2 -> st1)) -> P st2 a -> P st1 a
pSwitch split (P _ np pe pl)
= let nnp = fmap (\ (T ph pf pr) ->T (\ k st1 -> let (st2, back) = split st1
in ph (\ a st2' -> k a (back st2')) st2)
(\ k st1 -> let (st2, back) = split st1
in pf (\st2' -> k (back st2')) st2)
(\ k st1 -> let (st2, back) = split st1
in pr (\st2' -> k (back st2')) st2)) np
in mkParser nnp pe pl
parse :: (Eof t) => P t a -> t -> a
parse (P (T _ pf _) _ _ _) = fst . eval . pf (\ rest -> if eof rest then Step 0 ( Step 0 (Step 0 (Step 0 (Step 0 (error "ambiguous parser?")))))
else error "pEnd missing?")
parse_h :: (Eof t) => P t a -> t -> a
parse_h (P (T ph _ _) _ _ _) = fst . eval . ph (\ a rest -> if eof rest then push a (Step 0 (Step 0 (Step 0 (Step 0 (Step 0 (error "ambiguous parser?"))))) )
else error "pEnd missing?")
data Steps :: * -> * where
Step :: Progress -> Steps a -> Steps a
Apply :: forall a b. (b -> a) -> Steps b -> Steps a
Fail :: Strings -> [Strings -> (Cost , Steps a)] -> Steps a
Micro :: Int -> Steps a -> Steps a
End_h :: ([a] , [a] -> Steps r) -> Steps (a,r) -> Steps (a, r)
End_f :: [Steps a] -> Steps a -> Steps a
type Cost = Int
type Progress = Int
type Strings = [String]
apply :: Steps (b -> a, (b, r)) -> Steps (a, r)
apply = Apply (\(b2a, br) -> let (b, r) = br in (b2a b, r))
push :: v -> Steps r -> Steps (v, r)
push v = Apply (\ r -> (v, r))
apply2fst :: (b -> a) -> Steps (b, r) -> Steps (a, r)
apply2fst f = Apply (\ br -> let (b, r) = br in (f b, r))
noAlts :: Steps a
noAlts = Fail [] []
has_success :: Steps t -> Bool
has_success (Step _ _) = True
has_success _ = False
eval :: Steps a -> a
eval (Step n l) = trace' ("Step " ++ show n ++ "\n") (eval l)
eval (Micro _ l) = eval l
eval (Fail ss ls ) = trace' ("expecting: " ++ show ss) (eval (getCheapest 5 (map ($ss) ls)))
eval (Apply f l ) = f (eval l)
eval (End_f _ _ ) = error "dangling End_f constructor"
eval (End_h _ _ ) = error "dangling End_h constructor"
norm :: Steps a -> Steps a
norm (Apply f (Step p l )) = Step p (Apply f l)
norm (Apply f (Micro c l )) = Micro c (Apply f l)
norm (Apply f (Fail ss ls )) = Fail ss (applyFail (Apply f) ls)
norm (Apply f (Apply g l )) = norm (Apply (f.g) l)
norm (Apply f (End_f ss l )) = End_f (map (Apply f) ss) (Apply f l)
norm (Apply f (End_h _ _ )) = error "Apply before End_h"
norm steps = steps
applyFail :: (c -> d) -> [a -> (b, c)] -> [a -> (b, d)]
applyFail f = map (\ g -> \ ex -> let (c, l) = g ex in (c, f l))
best :: Steps a -> Steps a -> Steps a
x `best` y = norm x `best'` norm y
best' :: Steps b -> Steps b -> Steps b
End_f as l `best'` End_f bs r = End_f (as++bs) (l `best` r)
End_f as l `best'` r = End_f as (l `best` r)
l `best'` End_f bs r = End_f bs (l `best` r)
End_h (as, k_h_st) l `best'` End_h (bs, _) r = End_h (as++bs, k_h_st) (l `best` r)
End_h as l `best'` r = End_h as (l `best` r)
l `best'` End_h bs r = End_h bs (l `best` r)
Fail sl ll `best'` Fail sr rr = Fail (sl ++ sr) (ll++rr)
Fail _ _ `best'` r = r
l `best'` Fail _ _ = l
Step n l `best'` Step m r
| n == m = Step n (l `best` r)
| n < m = Step n (l `best` Step (m n) r)
| n > m = Step m (Step (n m) l `best` r)
ls@(Step _ _) `best'` Micro _ _ = ls
Micro _ _ `best'` rs@(Step _ _) = rs
ls@(Micro i l) `best'` rs@(Micro j r)
| i == j = Micro i (l `best` r)
| i < j = ls
| i > j = rs
l `best'` r = error "missing alternative in best'"
getCheapest :: Int -> [(Int, Steps a)] -> Steps a
getCheapest _ [] = error "no correcting alternative found"
getCheapest n l = snd $ foldr (\(w,ll) btf@(c, l)
-> if w < c
then let new = (traverse n ll w c)
in if new < c then (new, ll) else btf
else btf
) (maxBound, error "getCheapest") l
traverse :: Int -> Steps a -> Int -> Int -> Int
traverse 0 _ v c = trace' ("traverse " ++ show' 0 v c ++ " choosing" ++ show v ++ "\n") v
traverse n (Step _ l) v c = trace' ("traverse Step " ++ show' n v c ++ "\n") (traverse (n 1 ) l (v n) c)
traverse n (Micro x l) v c = trace' ("traverse Micro " ++ show' n v c ++ "\n") (traverse n l v c)
traverse n (Apply _ l) v c = trace' ("traverse Apply " ++ show n ++ "\n") (traverse n l v c)
traverse n (Fail m m2ls) v c = trace' ("traverse Fail " ++ show m ++ show' n v c ++ "\n")
(foldr (\ (w,l) c' -> if v + w < c' then traverse (n 1 ) l (v+w) c'
else c') c (map ($m) m2ls)
)
traverse n (End_h ((a, lf)) r) v c = traverse n (lf a `best` removeEnd_h r) v c
traverse n (End_f (l :_) r) v c = traverse n (l `best` r) v c
show' :: (Show a, Show b, Show c) => a -> b -> c -> String
show' n v c = "n: " ++ show n ++ " v: " ++ show v ++ " c: " ++ show c
removeEnd_h :: Steps (a, r) -> Steps r
removeEnd_h (Fail m ls ) = Fail m (applyFail removeEnd_h ls)
removeEnd_h (Step ps l ) = Step ps (removeEnd_h l)
removeEnd_h (Apply f l ) = error "not in history parsers"
removeEnd_h (Micro c l ) = Micro c (removeEnd_h l)
removeEnd_h (End_h (as, k_st ) r ) = k_st as `best` removeEnd_h r
removeEnd_f :: Steps r -> Steps [r]
removeEnd_f (Fail m ls) = Fail m (applyFail removeEnd_f ls)
removeEnd_f (Step ps l) = Step ps (removeEnd_f l)
removeEnd_f (Apply f l) = Apply (map' f) (removeEnd_f l)
where map' f ~(x:xs) = f x : map f xs
removeEnd_f (Micro c l ) = Micro c (removeEnd_f l)
removeEnd_f (End_f(s:ss) r) = Apply (:(map eval ss)) s
`best`
removeEnd_f r
data Nat = Zero Nat
| Succ Nat
| Infinite
| Unspecified
| Hole
deriving Show
getLength :: Nat -> Nat
getLength (Zero l) = l
getLength l = l
addLength n (P t nep e l) = P t nep e (addLength' n l)
addLength' :: Int -> Nat -> Nat
addLength' n (Zero _) = fromInt n
addLength' n (Succ m) = Succ (addLength' n m)
addLength' n Infinite = Infinite
addLength' n Unspecified = Unspecified
addLength' n Hole = fromInt n
fromInt n = if n>= 0 then (n `times` Succ) (Zero undefined) else error "error: negative argument passed to addlength"
where times :: Int -> (Nat -> Nat) -> Nat -> Nat
times 0 _ v = v
times n f v = times (n1) f (f v)
nat_min :: Nat -> Nat -> Int -> ( Nat
, Bool
)
nat_min (Zero l) (Zero r) n = trace' "Both Zero in nat_min\n" (Zero (trace' "Should not be called unless merging?" (fst(nat_min l r (n+1)))), False)
nat_min l rr@(Zero r) n = trace' "Right Zero in nat_min\n" (let (m,_) = nat_min l r (n+1)
in (Zero m, True))
nat_min ll@(Zero l) r n = trace' "Left Zero in nat_min\n" (let (m,_) = nat_min l r (n+1)
in (Zero m, False))
nat_min (Succ ll) (Succ rr) n = if n > 1000 then error "problem with comparing lengths"
else trace' ("Succ in nat_min " ++ show n ++ "\n")
(let (v, b) = nat_min ll rr (n+1) in (Succ v, b))
nat_min Infinite r _ = trace' "Left Infinite in nat_min\n" (r, True)
nat_min l Infinite _ = trace' "Right Infinite in nat_min\n" (l, False)
nat_min Hole r _ = error "canot compute minmal length of a parser due to occurrence of a moadic bind, use addLength to override"
nat_min l Hole _ = error "canot compute minmal length of a parser due to occurrence of a moadic bind, use addLength to override"
nat_min l Unspecified _ = (l , False)
nat_min Unspecified r _ = (r , False)
nat_add :: Nat -> Nat -> Nat
nat_add (Zero _) r = trace' "Zero in add\n" r
nat_add (Succ l) r = trace' "Succ in add\n" (Succ (nat_add l r))
nat_add Infinite _ = trace' "Infinite in add\n" Infinite
nat_add Hole _ = Hole
nat_add Unspecified r = trace' "Unspecified in add\n" Unspecified
trace' :: String -> b -> b
trace' m v = v