module testclass import StdEnv import Data.Maybe import Data.Either import Data.Functor import Control.Applicative import Control.Monad import Control.Monad.State import Text.Parsers.Simple.Chars import Text.Parsers.Simple.Core class parsable a ~b :: a -> Parser Char b instance parsable IntParse Int where parsable IntParse = foldl (\a d->a*10 + digitToInt d) 0 <$> some pDigit instance parsable (AltParse a) b | parsable a b where parsable (l |. r) = parsable l <|> parsable r :: IntParse = IntParse :: AltParse a = (|.) infixl 1 a a Start = 42 //:: In a b = (:.) infix 0 a b // //:: Gram // = Lit String // | Int // | (-.) infixr 2 Gram Gram // | (|.) infixl 1 Gram Gram // | *! Gram // | ?! Gram //Lits = foldr1 (|.) o map Lit //foldr1 f [x:xs] = foldr f x xs //:: Gast // = INT Int // | LIT String // | BIN Gast Gast // | OPT (Maybe Gast) // | MANY [Gast] // //parseFromGram :: Gram -> Parser String Gast //parseFromGram Int = INT o toInt <$> pSatisfy (\s->toString (toInt s) == s) //parseFromGram (Lit i) = LIT <$> pSatisfy ((==)i) //parseFromGram (?! g) = OPT <$> optional (parseFromGram g) //parseFromGram (*! g) = MANY <$> many (parseFromGram g) //parseFromGram (a -. b) = BIN <$> parseFromGram a <*> parseFromGram b //parseFromGram (a |. b) = parseFromGram a <|> parseFromGram b // ////Start = runParser (parseFromGram gram) [".","."] //Start = printeval <$> parse (parseFromGram gram) ["4","*","2","*","1","*","(","3","^","3","^","3",")"] //where // gram = // let lit = Lit "(" -. expr -. Lit ")" // |. Int // pow = lit -. ?! (Lit "^" -. pow) // fac = pow -. *! (Lits ["*","/"] -. pow) // expr = fac -. *! (Lits ["+","-","%"] -. fac) // in expr // // printeval a = (eval a, print a) // // eval :: Gast -> Maybe Int // eval (BIN (LIT "(") (BIN e (LIT ")"))) = eval e // eval (INT i) = Just i // eval (LIT _) = Nothing // eval (BIN l (OPT Nothing)) = eval l // eval (BIN l (OPT (Just a))) = eval (BIN l a) // //Right associative operators // eval (BIN l (BIN (LIT op) r)) = op2op op <*> eval l <*> eval r // //Left associative operators // eval (BIN l (MANY [])) = eval l // eval (BIN l (MANY [BIN (LIT op) r:rest])) // = eval (BIN (BIN l (BIN (LIT op) r)) (MANY rest)) // eval e = abort ("eval: " +++ printToString e +++ "\n") // // print :: Gast -> String // print (BIN (LIT "(") (BIN e (LIT ")"))) = "(" +++ print e +++ ")" // print (INT i) = toString i // print (LIT l) = l // print (BIN l (OPT Nothing)) = print l // print (BIN l (OPT (Just a))) = print (BIN l a) // //Right associative operators // print (BIN l (BIN (LIT op) r)) = "(" +++ print l +++ op +++ print r +++ ")" // //Left associative operators // print (BIN l (MANY [])) = print l // print (BIN l (MANY [BIN (LIT op) r:rest])) // = print (BIN (BIN l (BIN (LIT op) r)) (MANY rest)) // print e = printToString e +++ "\n" // // op2op "+" = Just (+) // op2op "-" = Just (-) // op2op "*" = Just (*) // op2op "/" = Just (/) // op2op "%" = Just (rem) // op2op "^" = Just (^) // op2op _ = Nothing // //import Text.GenPrint //derive gPrint Gast, Maybe