-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathParser.hs
74 lines (58 loc) · 1.78 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
74
module Parser where
import Types
import Text.ParserCombinators.Parsec hiding ((<|>))
import qualified Text.Parsec.Token as T
import Text.Parsec.Language
import Text.Parsec.Expr
import Control.Applicative
moleculeDef :: LanguageDef st
moleculeDef = emptyDef
{ T.opLetter = oneOf "+|"
, T.reservedOpNames = words "+ | \\ ."
, T.reservedNames = words "t f"
}
molecule :: T.TokenParser st
molecule = T.makeTokenParser moleculeDef
identifier = T.identifier molecule
reservedOp = T.reservedOp molecule
reserved = T.reserved molecule
integer = T.integer molecule
whiteSpace = T.whiteSpace molecule
parens = T.parens molecule
binary name label assoc = Infix (reservedOp name *> pure (\x y -> (label x y))) assoc
opTable = [
[ binary "+" (:+:) AssocLeft
, binary "|" (:|:) AssocLeft]
, [app] ]
app = Infix space AssocLeft
where space = whiteSpace
*> notFollowedBy (choice . map reservedOp $ T.reservedOpNames moleculeDef)
*> pure (\x y -> EApp x y)
value :: Parser MoleculeExpr
value = parens expression
<|> lambda
<|> int
<|> true
<|> false
<|> var
expression :: Parser MoleculeExpr
expression = buildExpressionParser opTable value
lambda :: Parser MoleculeExpr
lambda = do
reservedOp "\\"
name <- identifier
reservedOp "."
body <- liftA (foldr1 EApp) (many1 expression)
return $ EAbs name body
int :: Parser MoleculeExpr
int = liftA (EInt . fromInteger) integer
true :: Parser MoleculeExpr
true = reserved "t" *> pure ETrue
false :: Parser MoleculeExpr
false = reserved "f" *> pure EFalse
var :: Parser MoleculeExpr
var = liftA EVar identifier
parseMolecule :: String -> Either MoleculeError MoleculeExpr
parseMolecule e = case parse expression "(molecule)" e of
Left err -> Left . ParseError $ show err
Right e -> Right e