----------------------------------------------------------------------
-- Parsing arithmetic expressions using monadic parser combinators  --
----------------------------------------------------------------------

module Monadic_AE_Parser where

import Char
import Monad

-- a = Tokentyp, b= Ergebnistyp
newtype Parser a b = P ([a] -> [(b,[a])])

instance Monad (Parser a ) where
    return = result
    (>>=)  = bind
    fail _ = zero

-- basic parsers

result       :: b -> Parser a b
result x     = P (\s -> [(x,s)])

zero         :: Parser a b
zero         = P $ \_ -> []

item         :: Parser a a
item        = P $ \l -> case l of
	                  []      -> []
			  (a:as)  -> [(a,as)]


bind         :: Parser a b -> (b-> Parser a c) -> Parser a c
bind (P p) f     = P $ \s -> concat [q inp | (v,inp) <- p s, let P q = f v ]


instance MonadPlus (Parser a) where
    mzero = zero
    mplus = plus

plus         :: Parser a b -> Parser a b -> Parser a b
plus (P p) (P q)  = P $ \s -> p s ++ q s

infixr 4 ||| 
(|||) :: Parser a b -> Parser a b -> Parser a b
(|||) = mplus

checkChar         :: Char -> Parser Char Char
checkChar c = P $ \ cs -> case cs of 
                            []     -> []
                            (a:as) -> if c == a then [(c,as)] else []


tok          :: Eq a => [a] -> Parser a [a]
tok s       = P $ \cs -> loop s cs
                where loop []     cs            = [(s,cs)]
                      loop (s:ss) (c:cs) | s==c = loop ss cs
                      loop _      _             = []

----------------------------------------------------------
-- Translation of Grammar Rules into Parser Functions   --
----------------------------------------------------------
{-
-- E -> TH 
expr :: Parser Char [Int]
expr = term                 >>= \lt -> 
       hexpr                >>= \le ->
       return (1:lt++le)

-- H -> +TH | eps 
hexpr = (checkChar '+'        >>= \c -> 
         term                 >>= \lt -> 
         hexpr                >>= \le ->
         result (2:lt++le)) ||| result [3]

-- T -> FG
term = factor               >>= \lf -> 
       hterm                >>= \lt ->
       result (4:lf++lt)


-- G -> *FG | eps
hterm =  (checkChar '*'       >>= \c -> 
         factor               >>= \lf -> 
         hterm                >>= \lt ->
         result (5:lf++lt)) ||| result [6]
-- F -> (E) | a 
factor =   (checkChar '(' >>= \c -> 
           expr           >>= \le -> 
           checkChar ')' >>= \c ->
           result (7:le)) ||| (checkChar 'a' >>= \ c -> result [8])
-}
parseRD :: String -> [Int]
parseRD s = let (P parse_expr) = expr 
            in  case parse_expr s of
                  ((l,""):xs) -> l
                  _ -> error "syntax error in expression"

----------------------------------------------------------
-- Parser Functions Using do notation   --
----------------------------------------------------------

-- E -> TH 
expr :: Parser Char [Int]
expr = do lt <- term                  
          le <- hexpr                
          return (1:lt++le)

-- H -> +TH | eps 
hexpr = (do c  <- checkChar '+'  
            lt <- term 
            le <- hexpr  
            return (2:lt++le))
        |||    
        return [3]

-- T -> FG
term = do lf <- factor  
          lt <- hterm 
          return (4:lf++lt)


-- G -> *FG | eps
hterm =  (do c  <- checkChar '*'
             lf <- factor                
             lt <- hterm                
             return (5:lf++lt)) ||| return [6]
            
-- F -> (E) | a 
factor =   (do c  <- checkChar '('  
               le <- expr            
               c  <- checkChar ')' 
               return (7:le)) ||| 
           (do c <- checkChar 'a' 
               return [8])


----------------------------------------------------------
-- Parser Functions producing abstract syntax tree
----------------------------------------------------------

data Expr = Plus Expr Expr | Mult Expr Expr | Factor
            | Empty 
            deriving Show
           
empty :: Expr -> Bool           
empty Empty = True
empty _     = False 


-- E -> TH 
expr3 :: Parser Char Expr
expr3 = do lt <- term3                  
           le <- hexpr3                
           return (if empty le then lt else Plus lt le)

-- H -> +TH | eps 
hexpr3 = (do c  <- checkChar '+'  
             lt <- term3 
             le <- hexpr3  
             return (if empty le then lt else Plus lt le))
        |||    
        return Empty

-- T -> FG
term3 = do lf <- factor3  
           lt <- hterm3 
           return (if empty lt then lf else Mult lf lt)


-- G -> *FG | eps
hterm3 =  (do c  <- checkChar '*'
              lf <- factor3                
              lt <- hterm3               
              return (if empty lt then lf else Mult lf lt)) 
              ||| return Empty
            
-- F -> (E) | a 
factor3 =   (do c  <- checkChar '('  
                le <- expr3            
                c  <- checkChar ')' 
                return le) ||| 
            (do c <- checkChar 'a' 
                return Factor)

parseRD3 :: String -> Expr
parseRD3 s = let (P parse_expr) = expr3 
             in  case parse_expr s of
                   ((l,""):xs) -> l
                   _ -> error "syntax error in expression"
                   
                  