From: Mart Lubbers Date: Fri, 25 Jan 2019 14:33:35 +0000 (+0100) Subject: parserparser associativity X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=0ea5eda00d4894e4d4a0f46351c258e12d8307c1;p=clean-tests.git parserparser associativity --- diff --git a/parserParser/test.icl b/parserParser/test.icl index 5eb04d6..26a91d5 100644 --- a/parserParser/test.icl +++ b/parserParser/test.icl @@ -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