Grempa-0.1.1: examples/Ex4StateB.hs
{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable, DoRec #-}
module Ex4StateB (state, Expr, St, evalSt) where
import Control.Applicative
import Control.Monad.Reader
import Data.Data
import Data.List
import Data.Maybe
import Data.Parser.Grempa.Grammar
import Ex4StateLex
-- * Result data definitions
data Expr
= EApp Expr Expr
| EVar Integer
| ELam Expr
deriving (Eq, Show, Typeable)
-- | The parsing state is just a wrapper around the Reader monad to make it
-- possible to derive Typeable which is needed. We could also use a State
-- monad but that is not necessary in this example.
newtype St a = St { unSt :: Reader [String] a }
deriving (Typeable, Applicative, Functor, Monad, MonadReader [String])
evalSt = flip runReader [] . unSt
-- | Grammar for the language
state :: Grammar Tok Expr
state = do
rec
var <- rule [ fromTok <@> Var ""]
term1 <- levels $ do
rec
-- Now the rules return 'St' computations instead of their data result.
t1 <- lrule [ mkLam <@ Lambda <#> var <# RightArrow <#> t1 ]
t2 <- lrule [ mkApp <@> t2 <#> t3 ]
t3 <- lrule [ mkVar <@> var
, id <@ LParen <#> t1 <# RParen
]
return t1
-- Here we evaluate the final 'St' computation to get the result.
term <- rule [ evalSt <@> term1 ]
return term
where
mkLam :: String -> St Expr -> St Expr
mkLam v e = ELam <$> local (v :) e
mkApp :: St Expr -> St Expr -> St Expr
mkApp a b = EApp <$> a <*> b
mkVar :: String -> St Expr
mkVar v = do
vars <- ask
return $ EVar
$ snd
$ fromMaybe undefined
$ find ((== v) . fst) (zip vars [0..])