parserparser associativity
authorMart Lubbers <mart@martlubbers.net>
Fri, 25 Jan 2019 14:33:35 +0000 (15:33 +0100)
committerMart Lubbers <mart@martlubbers.net>
Fri, 25 Jan 2019 14:33:35 +0000 (15:33 +0100)
parserParser/test.icl

index 5eb04d6..26a91d5 100644 (file)
@@ -2,6 +2,8 @@ module test
 
 import StdEnv
 
+import Data.Maybe
+import Data.Either
 import Data.Functor
 import Control.Applicative
 import Control.Monad
@@ -12,34 +14,71 @@ import Text.Parsers.Simple.Core
 :: 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