parsing, update readme
This commit is contained in:
parent
098cf0832a
commit
f64bf8be2b
3 changed files with 43 additions and 33 deletions
|
|
@ -4,7 +4,8 @@ A (very WIP) lambda expression evaluator and debugger.
|
|||
|
||||
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
|
||||
- [ ] substitutions for known abstractions (numbers can be written and are displayed as numbers rather than lambda terms)
|
||||
- [ ] persisted variables
|
||||
|
|
|
|||
|
|
@ -1,36 +1,47 @@
|
|||
module Parser where
|
||||
|
||||
import Control.Monad (void)
|
||||
import Data.Char (isLetter)
|
||||
import Text.Parsec
|
||||
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)
|
||||
|
||||
instance Show Expr where
|
||||
show (Variable name) = name
|
||||
show (Abstraction (arg, body)) = "λ" ++ arg ++ ". " ++ show body
|
||||
show (Application (f, x)) = "(" ++ show f ++ " " ++ show x ++ ")"
|
||||
show (Abstraction arg body) = "λ" ++ arg ++ ". " ++ show body
|
||||
show (Application f x) = "(" ++ show f ++ " " ++ show x ++ ")"
|
||||
|
||||
ws :: Parser ()
|
||||
ws = skipMany (void space)
|
||||
|
||||
lexeme :: Parser a -> Parser a
|
||||
lexeme p = p <* ws
|
||||
|
||||
variable :: Parser Expr
|
||||
variable = do
|
||||
name <- many letter
|
||||
variable = lexeme $ do
|
||||
name <- many1 (satisfy (\c -> isLetter c && c /= 'λ'))
|
||||
return $ Variable name
|
||||
|
||||
abstraction :: Parser Expr
|
||||
abstraction = do
|
||||
abstraction = lexeme $ do
|
||||
_ <- void (char 'λ')
|
||||
variable <- many letter
|
||||
body <- parseExpr
|
||||
return $ Abstraction (variable, body)
|
||||
name <- many letter
|
||||
_ <- void (char '.' >> ws)
|
||||
body <- application
|
||||
return $ Abstraction name body
|
||||
|
||||
parseExpr :: Parser Expr
|
||||
parseExpr = variable <|> abstraction
|
||||
application :: Parser Expr
|
||||
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 content = case Text.Parsec.parse parseExpr "<input>" content of
|
||||
parse content = case Text.Parsec.parse application "<input>" content of
|
||||
Left err -> Left (show err)
|
||||
Right val -> Right val
|
||||
|
|
|
|||
|
|
@ -9,39 +9,37 @@ spec = do
|
|||
it "can parse variable" $
|
||||
(parse "x") `shouldBe` Right (Variable "x")
|
||||
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" $
|
||||
(parse "(λx.x x) (λx.x)") -- (λx.x) (λx.x) -> (λx.x)
|
||||
`shouldBe` Right
|
||||
( Application
|
||||
( Abstraction
|
||||
( "x",
|
||||
Application
|
||||
( Variable "x",
|
||||
Variable "x"
|
||||
"x"
|
||||
( Application
|
||||
(Variable "x")
|
||||
(Variable "x")
|
||||
)
|
||||
),
|
||||
Abstraction ("x", Variable "x")
|
||||
)
|
||||
(Abstraction "x" (Variable "x"))
|
||||
)
|
||||
it "it can parse successor" $
|
||||
(parse "λn.λf.λx.f (n f x)")
|
||||
`shouldBe` Right
|
||||
( Abstraction
|
||||
( "n",
|
||||
Abstraction
|
||||
( "f",
|
||||
Abstraction
|
||||
( "x",
|
||||
Application
|
||||
( Variable "f",
|
||||
Application
|
||||
"n"
|
||||
( Abstraction
|
||||
"f"
|
||||
( Abstraction
|
||||
"x"
|
||||
( Application
|
||||
( Variable "n",
|
||||
Variable "f"
|
||||
),
|
||||
Variable "x"
|
||||
)
|
||||
(Variable "f")
|
||||
( Application
|
||||
( Application
|
||||
(Variable "n")
|
||||
(Variable "f")
|
||||
)
|
||||
(Variable "x")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue