-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.hs
73 lines (60 loc) · 1.77 KB
/
Parser.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
module LamParser (Symbol, LamExpr(Sym, Lam, App), readExpr) where
import Text.Parsec
import Text.Parsec.String
type Symbol = String
data LamExpr = Sym Symbol
| Lam Symbol LamExpr -- 1 parameter functions
| App LamExpr LamExpr
instance Show LamExpr where show = showVal
showVal :: LamExpr -> String
showVal (Sym s) = s
showVal (Lam s v) = "\\" ++ s ++ " -> " ++ showVal v
showVal (App a b) = showFun a ++ " " ++ showArg b
where showArg v@(App _ _) = "(" ++ showVal v ++ ")"
showArg v = showVal v
showFun v@(Lam _ _) = "(" ++ showVal v ++ ")"
showFun v = showVal v
readExpr :: String -> LamExpr
readExpr str = case parse pLamExpr (take 10 str) str of
Left e -> error $ show e
Right expr -> expr
pLamExpr :: Parser LamExpr
pLamExpr = chainl1 (try $ pSpaces >> (pParentheseExpr <|> pVar <|> pLam)) (return App)
pSpaces :: Parser ()
pSpaces = spaces >> (try pComment <|> return ())
pComment :: Parser ()
pComment = do
_ <- string ";" <|> try (string "--")
_ <- many $ noneOf "\n"
_ <- char '\n'
pSpaces
pParentheseExpr :: Parser LamExpr
pParentheseExpr = do
_ <- char '('
expr <- pLamExpr
pSpaces
_ <- char ')'
return expr
pVar :: Parser LamExpr
pVar = do
x <- pName
return $ Sym x
pName :: Parser Symbol
pName = do
cs <- many1 (oneOf "+-*/<>=!@%&_?\"" <|> alphaNum)
if cs `elem` ["->", "--"]
then fail ""
else return cs
pLam :: Parser LamExpr
pLam = do
_ <- char '\\'
pSpaces
xs <- many1 (try $ pSpaces >> pName)
pSpaces
_ <- try $ string "->"
pSpaces
expr <- pLamExpr
return $ genLamList xs expr
genLamList :: [Symbol] -> LamExpr -> LamExpr
genLamList [] expr = expr
genLamList (x:xs) expr = Lam x $ genLamList xs expr