packages feed

expand-0.0.1: src/Utils.hs

{-# LANGUAGE Arrows, RecursiveDo, TemplateHaskell, EmptyDataDecls, NoMonomorphismRestriction, FlexibleInstances, FlexibleContexts, MultiParamTypeClasses, 
             PostfixOperators, ScopedTypeVariables, DataKinds, KindSignatures, FunctionalDependencies, UndecidableInstances #-}


module Utils where

import           Prelude hiding ((+), (*))
import           Control.Applicative
import           Control.Monad
import qualified GHC.TypeLits

import           Language.Grammars.Grammar
import           Language.Grammars.Murder
import           Language.Grammars.Murder.Derive
import           Language.Grammars.Murder.UUParsing
import           Language.Grammars.AspectAG
import qualified Text.ParserCombinators.UU.Core as UU

import Document.Decl

-- | Recognizes one or more characters except from the given list
someExcept :: [Char] -> PreProductions TL env String
someExcept cs = pSome $ iI value (sym $ anyExcept cs) Ii

-- | Recognizes zero or more characters except from the given list
manyExcept :: [Char] -> PreProductions TL env String
manyExcept cs = pMany $ iI value (sym $ anyExcept cs) Ii

-- | Recognizes one or more characters from the given list
someOf :: [Char] -> PreProductions TL env String
someOf cs = pSome $ iI value (sym $ anyOf cs) Ii

-- | Recognizes zero or more characters from the given list
manyOf :: [Char] -> PreProductions TL env String
manyOf cs = pMany $ iI value (sym $ anyOf cs) Ii


-- | Recognizes alternating occurences of p1 and p2, starting with p1
alternate :: PreProductions l env a -> PreProductions l env a -> PreProductions l env [a]
alternate p1 p2 = (:) <$> p1 <*> (alternate p2 p1 <|> pure []) 


result :: ParseResult a -> a
result (Ok x) = x
result (Rep x _) = x

errors (Ok _) = []
errors (Rep _ es) = es


parsePretty :: (Show a) => Parser a -> String -> IO a
parsePretty p input = 
    do print $ "parsing: " ++ input
       let res = parse p input
       case res of
           (Ok a)         -> return a
           (Rep a errors) -> let errors' = map (shorten 60) errors
                             in  forM_ errors' putStrLn >> putStrLn "" >> return a

shorten x e | length (show e) > x = take (x-3) (show e) ++ "..."
            | otherwise           = show e


-----
-- ? + * combinators
-----

{- 
-- (*) x = pMany $ iI x Ii :: PreProductions l [a] env
-- (+) x = pSome $ iI x iI :: PreProductions l [a] env
-- (?) x = iI Just x Ii <|> pure Nothing :: PreProductions l (Maybe a) env
-}


-- A transformation of a preproduction
newtype PreProductionsTrafo l env a b = PPT { unppt :: PreProductions l env a -> PreProductions l env b}

instance Idiomatic l env b g => Idiomatic l env a (PreProductionsTrafo l env a b -> g) where
    idiomatic prods f = idiomatic ((unppt f) prods)


-- a, b: PreProductions is a wrapper for: PreProductions l env a -> PreProductions l env b
-- x : type for a symbol in the production 
class Shortcuts l env a a' a'' b x| x -> l env a a' a'' b where
    (?) :: x -> PreProductionsTrafo l env a   b
    (+) :: x -> PreProductionsTrafo l env a'  b
    (*) :: x -> PreProductionsTrafo l env a'' b

instance Shortcuts TL env a a a a [Char] where
    (?) x = PPT (\prods -> prods <* pMaybe (Nothing, Just) (tr x))
    (+) x = PPT (\prods -> prods <* pMany (tr x))
    (*) x = PPT (\prods -> prods <* pSome (tr x))

instance Shortcuts TL env (Maybe a -> b) ([a] -> b) ([a] -> b) b (Symbol a t env) where
    (?) x = PPT (\prods -> prods <*> pMaybe (Nothing, Just) (sym x))
    (+) x = PPT (\prods -> prods <*> pSome (sym x))
    (*) x = PPT (\prods -> prods <*> pMany (sym x))

-- ignore the value of a symbol for the computation (idiomatic for <*)
data Ign a = Ign a
ign = Ign

{- Tried more general approach, not working

instance (Idiomatic l env f g, Idiomatic l env (a -> f) (x     -> g)) 
                            => Idiomatic l env (a -> f) (Ign x -> g) where
    idiomatic pprods (Ign symb) = idiomatic (pprods <*> (iI symb Ii :: PreProductions l env a))

-}

-- ignore PreProductions
instance Idiomatic l env f g => Idiomatic l env f (Ign (PreProductions l env a) -> g) where
    idiomatic prods (Ign prods') = idiomatic (prods <* prods')

-- ignore Non terminals
instance Idiomatic l env f g => Idiomatic l env f (Ign (Symbol a TNonT env) -> g) where
    idiomatic prods (Ign s) = idiomatic (prods <* sym s)

instance Idiomatic l env f g => Idiomatic l env f (Ign String -> g) where
    idiomatic prods (Ign str) = idiomatic (prods <* tr str)




-- bit of error reporting
class Error (e :: GHC.TypeLits.Symbol)

instance Error ("Missing a closing Ii") => Idiomatic l env x (PreProductions l a env) where
    idiomatic = undefined




-- also ignore PreProductions l env () and Symbol () t env
-- instance  Idiomatic l env f g  => Idiomatic  l env f (PreProductions l env () -> g) where
--    idiomatic isf is = idiomatic (isf <* is)

-- instance  Idiomatic l env f g  => Idiomatic  l env f (Symbol () t env -> g) where
--    idiomatic isf is = idiomatic (isf <* (sym is))