diff options
| author | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-10-17 16:45:29 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-10-17 16:45:29 +0200 |
| commit | dee78cba2ec18da811fd6f0499efe1bd27ad34e5 (patch) | |
| tree | ef34a61d88969adc75f37770409c816b6f8cfc76 /lambda-calcul | |
| parent | 78d2b3acf77dc0500d27836915dce99a9c368b53 (diff) | |
| download | lambda-nantes-dee78cba2ec18da811fd6f0499efe1bd27ad34e5.tar.gz | |
feat: parse λ-expr with multiple bindings
Diffstat (limited to 'lambda-calcul')
| -rw-r--r-- | lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs | 10 | ||||
| -rw-r--r-- | lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs | 13 |
2 files changed, 15 insertions, 8 deletions
diff --git a/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs b/lambda-calcul/haskell/src/Minilang/Lambda/Parser.hs index 545536d..8e97d46 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 +data AST = Sym Text | Abs [Text] AST deriving (Eq, Show) parse :: Text -> Either ParseError AST @@ -28,10 +28,10 @@ lambda = between lpar rpar - ( do - lexeme "lam" - binding <- pack <$> between lpar rpar identifier - Abs binding <$> ast + ( lexeme "lam" + *> ( (Abs . fmap pack <$> between lpar rpar (many identifier)) + <*> ast + ) ) lpar :: Parser Text diff --git a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs index c1eab27..ea7cd89 100644 --- a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs +++ b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs @@ -1,19 +1,26 @@ module Minilang.Lambda.ParserSpec where import Data.Text (Text, pack) +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 (..), elements, listOf) +import Test.QuickCheck (Arbitrary (..), NonEmptyList (..), elements, listOf) spec :: Spec spec = parallel $ do prop "parses an identifier as a variable" $ \(Identifier ident) -> parse ident `shouldBe` Right (Sym ident) + prop "parses a lambda-expression as an abstraction" $ \(Identifier ident) (Identifier body) -> - parse ("(lam (" <> ident <> ") " <> body <> ")") `shouldBe` Right (Abs ident (Sym body)) + parse ("(lam (" <> ident <> ") " <> body <> ")") `shouldBe` Right (Abs [ident] (Sym body)) + + 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 -newtype Identifier = Identifier Text +newtype Identifier = Identifier {unIdent :: Text} deriving (Eq, Show) instance Arbitrary Identifier where |
