{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedRecordDot #-} {-# HLINT ignore "Use const" #-} {-# HLINT ignore "Unused LANGUAGE pragma" #-} {-# HLINT ignore "Avoid lambda" #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE NoFieldSelectors #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} {-# LANGUAGE TypeApplications #-} module Test.SimpleParserSpec where import Test.Hspec import Text.Megaparsec import SimpleParser checkParse :: String -> Expr -> Expectation checkParse text expectedExpr = parse parseExpr "" text `shouldBe` Right expectedExpr checkEval :: String -> Int -> Expectation checkEval text expectedVal = fmap eval (parse parseExpr "" text) `shouldBe` Right expectedVal spec :: Spec spec = do describe "evaluate expressions" $ do it "arithmetic on literals" $ do eval (BinaryExpr Add (Literal 2) (Literal 3) ) `shouldBe` 5 eval (BinaryExpr Subtract (Literal 2) (Literal 3) ) `shouldBe` -1 eval (BinaryExpr Multiply (Literal 2) (Literal 3) ) `shouldBe` 6 eval (BinaryExpr Divide (Literal 7) (Literal 3) ) `shouldBe` 2 eval (UnaryExpr Negate (Literal 7) ) `shouldBe` -7 it "more complex arithmetic on literals" $ do eval (BinaryExpr Add (UnaryExpr Negate (Literal 1)) (BinaryExpr Divide (Literal 7) (Literal 3)) ) `shouldBe` 1 it "can parse basic expressions" $ do checkParse "2" (Literal 2) checkParse "2+3" (BinaryExpr Add (Literal 2) (Literal 3)) checkParse "2+3+5" (BinaryExpr Add (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5)) checkParse "2+3*5" (BinaryExpr Add (Literal 2) (BinaryExpr Multiply (Literal 3) (Literal 5))) checkParse "(2+3)*5" (BinaryExpr Multiply (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5) ) checkParse "((2+3))*5" (BinaryExpr Multiply (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5) ) it "can evaluate expressions correctly" $ do checkEval "2" 2 checkEval "3*4/2" 6 checkEval "2+3*6" 20 checkEval "1-2+3" (-4)