import StdEnv
+import Data.Maybe
+import Data.Either
import Data.Functor
import Control.Applicative
import Control.Monad
:: In a b = (:.) infix 0 a b
:: Gram
- = Def (Gram -> In Gram Gram)
- | Def2 ((Gram,Gram) -> In (Gram, Gram) Gram)
- | Lit String
+// = Def (Gram -> In Gram Gram)
+// | Def2 ((Gram,Gram) -> In (Gram, Gram) Gram)
+ = Lit String
| Int
| (-.) infixr 2 Gram Gram
- | (|.) infix 1 Gram Gram
+ | (|.) infixl 1 Gram Gram
+ | *! Gram
:: Gast
= INT Int
| LIT String
| BIN Gast Gast
+ | MANY [Gast]
parseFromGram :: Gram -> Parser String Gast
-parseFromGram (Def g) = let (body :. gram) = g body in parseFromGram gram
parseFromGram Int = INT o toInt <$> pSatisfy (\s->toString (toInt s) == s)
parseFromGram (Lit i) = LIT <$> pSatisfy ((==)i)
+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 = parse (parseFromGram gram) ["5"]
+Start = printeval <$> parse (parseFromGram gram) ["4","-","2","-","1"]
where
gram =
- Def \lit = Int
- |. Lit "(" -. expr -. Lit ")"
- Def \fac = lit -. Lit "*" -. fac
- |. lit -. Lit "/" -. fac
- |. lit :.
- Def \expr= fac -. Lit "+" -. expr
- |. fac -. Lit "-" -. expr
- |. fac :.
- expr
+ let lit = Lit "(" -. expr -. Lit ")"
+ |. Int
+ pow = lit -. Lit "^" -. pow
+ |. lit
+ fac = pow -. *! (Lit "*" -. pow)
+ |. pow
+ expr = fac -. *! (Lit "-" -. fac)
+ |. 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
+ //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
+ //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 _ = Nothing
+
+import Text.GenPrint
+derive gPrint Gast, Maybe