{-| Module : PP.Grammar Description : Common behavior for defined grammars Copyright : (c) 2017 Patrick Champion License : see LICENSE file Maintainer : chlablak@gmail.com Stability : provisional Portability : portable -} module PP.Grammar ( To , InputGrammar(..) , rules' ) where import Control.Exception import Data.Either import PP.Rule (Rule) import qualified Text.Parsec as P -- |Syntactic sugar -- For exemple: `case PP.parseAst input :: (PP.To Ebnf.Syntax) of ...` type To ast = Either P.ParseError ast -- |Type class for grammars class (Eq ast, Show ast) => InputGrammar ast where -- |Entry parser parser :: P.Parsec String () ast -- |Parse String to AST parseAst :: String -> To ast parseAst = P.parse parser "" -- |AST to String stringify :: ast -> String stringify = show -- |AST to canonical rules rules :: ast -> [Rule] -- |Transform terminals to lexical rules lexify :: ast -> ast lexify = id -- |Exception-safe version of `rules` rules' :: (InputGrammar ast) => ast -> IO (Either String [Rule]) rules' ast = do a <- try (evaluate $ rules ast) :: IO (Either SomeException [Rule]) case a of Left e -> return $ Left $ head $ lines $ displayException e Right r -> return $ Right r