parsing, update readme

This commit is contained in:
jackjohn7 2026-05-15 02:02:57 -05:00
parent 098cf0832a
commit f64bf8be2b
3 changed files with 43 additions and 33 deletions

View file

@ -4,7 +4,8 @@ A (very WIP) lambda expression evaluator and debugger.
I'd like to build the following: I'd like to build the following:
- [ ] parsing with parsec - [X] parsing with parsec
- need to harden tests a bit more but existing tests pass
- [ ] alpha/beta reduction to beta normal - [ ] alpha/beta reduction to beta normal
- [ ] substitutions for known abstractions (numbers can be written and are displayed as numbers rather than lambda terms) - [ ] substitutions for known abstractions (numbers can be written and are displayed as numbers rather than lambda terms)
- [ ] persisted variables - [ ] persisted variables

View file

@ -1,36 +1,47 @@
module Parser where module Parser where
import Control.Monad (void) import Control.Monad (void)
import Data.Char (isLetter)
import Text.Parsec import Text.Parsec
import Text.Parsec.String (Parser) import Text.Parsec.String (Parser)
data Expr = Variable String | Abstraction (String, Expr) | Application (Expr, Expr) data Expr = Variable String | Abstraction String Expr | Application Expr Expr
deriving (Eq) deriving (Eq)
instance Show Expr where instance Show Expr where
show (Variable name) = name show (Variable name) = name
show (Abstraction (arg, body)) = "λ" ++ arg ++ ". " ++ show body show (Abstraction arg body) = "λ" ++ arg ++ ". " ++ show body
show (Application (f, x)) = "(" ++ show f ++ " " ++ show x ++ ")" show (Application f x) = "(" ++ show f ++ " " ++ show x ++ ")"
ws :: Parser () ws :: Parser ()
ws = skipMany (void space) ws = skipMany (void space)
lexeme :: Parser a -> Parser a
lexeme p = p <* ws
variable :: Parser Expr variable :: Parser Expr
variable = do variable = lexeme $ do
name <- many letter name <- many1 (satisfy (\c -> isLetter c && c /= 'λ'))
return $ Variable name return $ Variable name
abstraction :: Parser Expr abstraction :: Parser Expr
abstraction = do abstraction = lexeme $ do
_ <- void (char 'λ') _ <- void (char 'λ')
variable <- many letter name <- many letter
body <- parseExpr _ <- void (char '.' >> ws)
return $ Abstraction (variable, body) body <- application
return $ Abstraction name body
parseExpr :: Parser Expr application :: Parser Expr
parseExpr = variable <|> abstraction application = lexeme $ chainl1 atom (return Application)
parens :: Parser Expr
parens = lexeme $ between (char '(') (char ')') application
atom :: Parser Expr
atom = variable <|> abstraction <|> parens
parse :: String -> Either String Expr parse :: String -> Either String Expr
parse content = case Text.Parsec.parse parseExpr "<input>" content of parse content = case Text.Parsec.parse application "<input>" content of
Left err -> Left (show err) Left err -> Left (show err)
Right val -> Right val Right val -> Right val

View file

@ -9,39 +9,37 @@ spec = do
it "can parse variable" $ it "can parse variable" $
(parse "x") `shouldBe` Right (Variable "x") (parse "x") `shouldBe` Right (Variable "x")
it "can parse identity abstraction" $ it "can parse identity abstraction" $
(parse "λx.x") `shouldBe` Right (Abstraction ("x", Variable "x")) (parse "λx.x") `shouldBe` Right (Abstraction "x" (Variable "x"))
it "can parse mockingbird of identity" $ it "can parse mockingbird of identity" $
(parse "(λx.x x) (λx.x)") -- (λx.x) (λx.x) -> (λx.x) (parse "(λx.x x) (λx.x)") -- (λx.x) (λx.x) -> (λx.x)
`shouldBe` Right `shouldBe` Right
( Application ( Application
( Abstraction ( Abstraction
( "x", "x"
Application ( Application
( Variable "x", (Variable "x")
Variable "x" (Variable "x")
) )
),
Abstraction ("x", Variable "x")
) )
(Abstraction "x" (Variable "x"))
) )
it "it can parse successor" $ it "it can parse successor" $
(parse "λn.λf.λx.f (n f x)") (parse "λn.λf.λx.f (n f x)")
`shouldBe` Right `shouldBe` Right
( Abstraction ( Abstraction
( "n", "n"
Abstraction ( Abstraction
( "f", "f"
Abstraction ( Abstraction
( "x", "x"
Application ( Application
( Variable "f", (Variable "f")
Application ( Application
( Application ( Application
( Variable "n", (Variable "n")
Variable "f" (Variable "f")
),
Variable "x"
) )
(Variable "x")
) )
) )
) )