hermit-0.3.0.0: src/HERMIT/ParserCore.y
{
{-# LANGUAGE CPP #-}
module HERMIT.ParserCore (parseCore, parseCoreExprT, parse2beforeBiR, parse3beforeBiR) where
import Control.Arrow
import Control.Monad.Reader
import Data.Char (isSpace, isDigit)
import HERMIT.Context
import HERMIT.External
import HERMIT.GHC
import HERMIT.Kure
import HERMIT.Monad
import HERMIT.Syntax (isCoreInfixIdChar, isCoreIdFirstChar, isCoreIdChar)
import HERMIT.Dictionary.Common
import Language.KURE.MonadCatch (prefixFailMsg)
import Language.Haskell.TH as TH
}
%name parser
%tokentype { Token }
%error { parseError }
%monad { CoreParseM } { >>= } { return }
%token
'%forall' { Tforall }
'%rec' { Trec }
'%let' { Tlet }
'%in' { Tin }
'%case' { Tcase }
'%of' { Tof }
'%cast' { Tcast }
'%note' { Tnote }
'%external' { Texternal }
'%local' { Tlocal }
'%_' { Twild }
'(' { Toparen }
')' { Tcparen }
'{' { Tobrace }
'}' { Tcbrace }
'#' { Thash}
'=' { Teq }
':' { Tcolon }
'::' { Tcoloncolon }
':=:' { Tcoloneqcolon }
'*' { Tstar }
'->' { Tarrow }
'\\' { Tlambda}
'@' { Tat }
'.' { Tdot }
'?' { Tquestion}
';' { Tsemicolon }
NAME { Tname $$ }
CNAME { Tcname $$ }
INTEGER { Tinteger $$ }
RATIONAL { Trational $$ }
STRING { Tstring $$ }
CHAR { Tchar $$ }
%%
-- | Top level expression term.
expr : app { $1 }
app : app arg { App $1 $2 }
| arg { $1 }
arg : '(' expr ')' { $2 }
| '(' ')' {% lookupName "()" Var }
| var { $1 }
| intlit { $1 }
| strlit { $1 }
intlit : INTEGER {% mkIntExpr' $1 } -- mkIntLit makes a primitive Int#
strlit : STRING {% lift $ mkStringExpr $1 }
var : NAME {% lookupName $1 varToCoreExpr }
{
mkIntExpr' :: Integer -> CoreParseM CoreExpr
#if __GLASGOW_HASKELL__ > 706
mkIntExpr' i = do
dflags <- lift getDynFlags
return $ mkIntExpr dflags i
#else
mkIntExpr' i = return $ mkIntExpr i
#endif
lookupName :: String -> (Id -> CoreExpr) -> CoreParseM CoreExpr
lookupName nm k = do
c <- ask
v <- lift $ prefixFailMsg (nm ++ " lookup: ") $ findId (TH.mkName nm) c
return (k v)
type CoreParseM a = ReaderT HermitC HermitM a
parseError :: Monad m => [Token] -> m a
parseError ts = fail $ "core parse error: " ++ show ts
data Token
= Tforall
| Trec
| Tlet
| Tin
| Tcase
| Tof
| Tcast
| Tnote
| Texternal
| Tlocal
| Twild --
| Toparen --
| Tcparen --
| Tobrace
| Tcbrace
| Thash
| Teq
| Tcolon --
| Tcoloncolon --
| Tcoloneqcolon
| Tstar
| Tarrow
| Tlambda --
| Tat
| Tdot
| Tquestion
| Tsemicolon
| Tname String
| Tcname String
| Tinteger Integer
| Trational Float
| Tstring String
| Tchar Char
deriving (Eq, Show)
lexer :: String -> Either String [Token]
lexer [] = Right []
lexer ('_' :cs) = fmap (Twild:) $ lexer cs
lexer ('(' :cs) = fmap (Toparen:) $ lexer cs
lexer (')' :cs) = fmap (Tcparen:) $ lexer cs
lexer (':':':':cs) = fmap (Tcoloncolon:) $ lexer cs
-- lexer (':' :cs) = fmap (Tcolon:) $ lexer cs
lexer ('\\':cs) = fmap (Tlambda:) $ lexer cs
lexer ('-':'>':cs) = fmap (Tarrow:) $ lexer cs
lexer ('\"':cs) = let (str,rest) = span (/='\"') cs
in case rest of
('\"':cs') -> fmap (Tstring str:) $ lexer cs'
_ -> Left "lexer: no matching quote"
lexer s@(c:cs) | isSpace c = lexer cs
| isDigit c = let (i,s') = span isDigit s
in fmap (Tinteger (read i):) $ lexer s'
| isCoreIdFirstChar c = let (i,s') = span isCoreIdChar s
in fmap (Tname i:) $ lexer s'
| isCoreInfixIdChar c = let (op,s') = span isCoreInfixIdChar s
in fmap (Tname op:) $ lexer s'
lexer s = Left $ "lexer: no match on " ++ s
---------------------------------------------
parseCore :: CoreString -> HermitC -> HermitM CoreExpr
parseCore (CoreString s) c =
case lexer s of
Left msg -> fail msg
Right tokens -> runReaderT (parser tokens) c
---------------------------------------------
-- These three should probably go somewhere else.
-- | Parse a 'CoreString' to a 'CoreExpr', using the current context.
parseCoreExprT :: CoreString -> TranslateH a CoreExpr
parseCoreExprT = contextonlyT . parseCore
parse2beforeBiR :: (CoreExpr -> CoreExpr -> BiRewriteH a) -> CoreString -> CoreString -> BiRewriteH a
parse2beforeBiR f s1 s2 = beforeBiR (parseCoreExprT s1 &&& parseCoreExprT s2) (uncurry f)
parse3beforeBiR :: (CoreExpr -> CoreExpr -> CoreExpr -> BiRewriteH a) -> CoreString -> CoreString -> CoreString -> BiRewriteH a
parse3beforeBiR f s1 s2 s3 = beforeBiR ((parseCoreExprT s1 &&& parseCoreExprT s2) &&& parseCoreExprT s3) ((uncurry.uncurry) f)
---------------------------------------------
}