module Support.Unparse(Unparse(), Unparsable(..), unparse, unparse', Side(..), atom, atomize, bop, pop, fixitize) where import Doc.DocLike data Unparse a = Atom a | Pre a (Unparse a) | Fix (Unparse a) a (Unparse a) !Side !Int | Atomized (Unparse a) | Fixitized !Side !Int (Unparse a) data Side = R | L | N deriving(Eq) atom :: a -> Unparse a atom s = Atom s atomize :: Unparse a -> Unparse a atomize (Atomized x) = Atomized x atomize (Atom a) = Atom a atomize x = Atomized x fixitize :: (Side,Int) -> Unparse a -> Unparse a fixitize (s,i) a = Fixitized s i a pop :: a -> Unparse a -> Unparse a pop = Pre bop :: (Side,Int) -> a -> Unparse a -> Unparse a -> Unparse a bop (s,i) op a b = Fix a op b s i data Unparsable a = Unparsable { unparseGroup :: a -> a, unparseCat :: a -> a -> a } data Fix = FAtom | FPre | FFix !Side !Int unparse :: DocLike a => Unparse a -> a unparse up = unparse' Unparsable { unparseGroup = parens, unparseCat = (<>) } up unparse' :: Unparsable a -> Unparse a -> a unparse' Unparsable { unparseGroup = upg, unparseCat = (<>) } up = fst $ f up where f (Atom a) = atom a f (Atomized a) = (fst $ f a, FAtom) f (Fixitized s i a) = (fst $ f a, FFix s i) f (Pre a up) = pop a (f up) f (Fix a op b s i) = bop (s,i) op (f a) (f b) bop (f1,f2) s (a,FAtom) (b,FAtom) = (sop s a b, FFix f1 f2) bop f@(f1,f2) s (a,af) (b,bf) | lts L f af && lts R f bf = (sop s a b, FFix f1 f2) bop f s (a,af) b | not (lts L f af) = bop f s (mkatom (a,af)) b bop f s a (b,bf) | not (lts R f bf) = bop f s a (mkatom (b,bf)) bop _ _ _ _ = error "bop" pop s (x, FAtom) = ( s <> x, FPre) pop s x = pop s $ mkatom x atom a = (a,FAtom) mkatom (a,FAtom) = (a,FAtom) mkatom (a,_) = ( upg a , FAtom) sop op a b = a <> (op <> b) lts :: Side -> (Side,Int) -> Fix -> Bool lts _ _ FAtom = True lts _ _ FPre = True lts _ (_,n') (FFix _ n ) | n' /= n = n' < n lts R (R,_) (FFix R _ ) = True lts L (L,_) (FFix L _ ) = True lts _ _ _ = False --lts _ (N,_) (Fix (N,_)) = False --type Unparse a = (a, Fix) {- bop :: Unparsable a => (Side,Int) -> a -> Unparse a -> Unparse a -> Unparse a --bop f "" a b@(_,Pre) = bop f "" a (mkatom b) bop (f1,f2) s (a,Atom) (b,Atom) = (sopns s a b, Fix f1 f2) bop f@(f1,f2) s (a,af) (b,bf) | lts L f af && lts R f bf = (sop s a b, Fix f1 f2) bop f s (a,af) b | not (lts L f af) = bop f s (mkatom (a,af)) b bop f s a (b,bf) | not (lts R f bf) = bop f s a (mkatom (b,bf)) pop :: Unparsable a => a -> Unparse a -> Unparse a pop s (x, Atom) = (unparseCat s x, Pre) pop s x = pop s $ mkatom x --sop "" a b = a ++ " " ++ b sop op a b = unparseSpace a $ unparseSpace op b --sopns "" a b = a ++ " " ++ b sopns op a b = unparseCat a $ unparseCat op b mkatom (a,Atom) = (a,Atom) mkatom (a,_) = ( unparseGroup a , Atom) --sop "" a b = a ++ " " ++ b sop op a b = unparseSpace a $ unparseSpace op b --sopns "" a b = a ++ " " ++ b sopns op a b = unparseCat a $ unparseCat op b mkatom (a,Atom) = (a,Atom) mkatom (a,_) = ( unparseGroup a , Atom) instance Unparsable Doc where unparseCat = (<>) unparseSpace = (<>) unparseGroup = parens class Unparsable a where unparseGroup :: a -> a unparseCat :: a -> a -> a unparseSpace :: a -> a -> a unparseConcat :: [a] -> a unparseConcat = foldl1 unparseCat instance Unparsable String where unparseGroup x = "(" ++ x ++ ")" unparseCat x y = x ++ y unparseSpace x y = x ++ " " ++ y unparseConcat xs = concat xs instance Unparsable () where unparseGroup _ = () unparseCat _ _ = () unparseSpace _ _ = () infixr 9 . infixr 8 ^, ^^, ** infixl 7 *, /, `quot`, `rem`, `div`, `mod` infixl 6 +, - -- The (:) operator is built-in syntax, and cannot legally be given -- a fixity declaration; but its fixity is given by: -- infixr 5 : infix 4 ==, /=, <, <=, >=, > infixr 3 && infixr 2 || infixl 1 >>, >>= infixr 1 =<< infixr 0 $, $!, `seq` a + b * c a + (b * c) d + a * b + c * d plus = bop ((L,6)) "+" minus = bop ((L,6)) "-" times = bop ((L,7)) "*" pow = bop ((L,8)) "^" eq = bop ((N,4)) "==" a,b,c,d,x,y, abcdr, abcdl, eql :: (String, Fix) a = text "a" b = text "b" c = text "c" d = text "d" x = text "x" y = text "y" abcdr = foldl1 plus [a,b,c,d] abcdl = foldr1 plus [a,b,c,d] eql = foldl1 eq [a,b,c] z = eq (plus a b) (pow (times b c) abcdl) `eq` eql g = minus (plus (times (plus a b) (plus b c)) abcdr) abcdl main = putStrLn $ fst $ foldl1 plus [g,eql, z ] -}