summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud@pankzsoft.com>2025-10-17 16:54:43 +0200
committerArnaud Bailly <arnaud@pankzsoft.com>2025-10-17 16:54:43 +0200
commit0837921dae14ec7f1e6008f1f85cbd056ad2aced (patch)
tree61f6f73feead72ca3ec5dbe67196f9b43f12019b
parent3b20f8a9e85696b86f698e1bdbdbd31b786b77c2 (diff)
downloadlambda-nantes-0837921dae14ec7f1e6008f1f85cbd056ad2aced.tar.gz
feat: parse an application
-rw-r--r--lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs4
-rw-r--r--lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs15
2 files changed, 13 insertions, 6 deletions
diff --git a/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs b/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs
index e60d761..f18ac74 100644
--- a/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs
+++ b/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs
@@ -13,7 +13,7 @@ type Parser = Parsec Void Text
data ParseError = ParseError Text
deriving (Eq, Show)
-data AST = Sym Text | Abs [Text] AST | App AST AST
+data AST = Sym Text | Abs [Text] AST | App AST AST [AST]
deriving (Eq, Show)
parse :: Text -> Either ParseError AST
@@ -28,7 +28,7 @@ app =
between
lpar
rpar
- (App <$> ast <*> ast)
+ (App <$> ast <*> ast <*> many ast)
lambda :: Parser AST
lambda =
diff --git a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
index b52017a..13279e9 100644
--- a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
+++ b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
@@ -5,7 +5,7 @@ import qualified Data.Text as Text
import Minilang.Lambda.Parser (AST (..), initialChars, parse, restChars)
import Test.Hspec (Spec, parallel, shouldBe)
import Test.Hspec.QuickCheck (prop)
-import Test.QuickCheck (Arbitrary (..), NonEmptyList (..), elements, listOf)
+import Test.QuickCheck (Arbitrary (..), NonEmptyList (..), elements, listOf, (==>))
spec :: Spec
spec = parallel $ do
@@ -17,11 +17,18 @@ spec = parallel $ do
prop "parses a lambda-expression with multiple bindings as an abstraction" $ \(NonEmpty idents) (Identifier body) ->
let vars = unIdent <$> idents
- nestedAbs = Abs vars (Sym body)
- in parse ("(lam (" <> Text.unwords vars <> ") " <> body <> ")") `shouldBe` Right nestedAbs
+ abs = Abs vars (Sym body)
+ in parse ("(lam (" <> Text.unwords vars <> ") " <> body <> ")") `shouldBe` Right abs
prop "parses an application" $ \(Identifier ident1) (Identifier ident2) ->
- parse ("(" <> ident1 <> " " <> ident2 <> ")") `shouldBe` Right (App (Sym ident1) (Sym ident2))
+ parse ("(" <> ident1 <> " " <> ident2 <> ")") `shouldBe` Right (App (Sym ident1) (Sym ident2) [])
+
+ prop "parses multiple applications" $ \(NonEmpty idents) ->
+ (length idents >= 2) ==>
+ let vars = unIdent <$> idents
+ (a : b : rest) = vars
+ app = App (Sym a) (Sym b) (Sym <$> rest)
+ in parse ("(" <> Text.unwords vars <> ")") `shouldBe` Right app
newtype Identifier = Identifier {unIdent :: Text}
deriving (Eq, Show)