packages feed

Grempa-0.1.1: examples/Ex4StateA.hs

{-# LANGUAGE StandaloneDeriving, GeneralizedNewtypeDeriving, DeriveDataTypeable, DoRec #-}
module Ex4StateA (state, Expr, St, evalSt) where

import Control.Applicative
import Control.Monad.State
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)

type St a = [String] -> a
evalSt f = f []

-- | Grammar for the language
state :: Grammar Tok Expr
state = do
  rec
    var   <- rule [ fromTok <@> Var ""]
    term1 <- levels $ do
      rec
        -- Here the rules return functions of type 'St'.
        t1 <- lrule [ mkLam <@  Lambda <#> var <# RightArrow <#> t1 ]
        t2 <- lrule [ mkApp <@> t2  <#> t3 ]
        t3 <- lrule [ mkVar <@> var
                    , id    <@  LParen <#> t1 <# RParen
                    ]
      return t1
      -- Here we apply the final 'St' function to get the real result.
    term <- rule [ evalSt <@> term1 ]
  return term
  where
    mkLam :: String -> St Expr -> St Expr
    mkLam v e st = ELam (e (v : st))

    mkApp :: St Expr -> St Expr -> St Expr
    mkApp a b st = EApp (a st) (b st)

    mkVar :: String -> St Expr
    mkVar v vars = EVar $ snd
                        $ fromMaybe undefined
                        $ find ((== v) . fst) (zip vars [0..])