-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParseProg.hs
175 lines (148 loc) · 5.66 KB
/
ParseProg.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
module ParseProg where
import Parse
import GHC.Base
type Name = String
data Expr a
= EVar Name -- Variables
| ENum Int -- Numbers
| EConstr Int Int -- Constructor tag arity
| EAp (Expr a) (Expr a) -- Applications
| ELet -- Let(rec) expressions {in Expr using IsRec you use the constructor ELet for modelling both let and letrec}
IsRec -- boolen with True = recursive
[(a, Expr a)] -- Definitions
(Expr a) -- Body of let(rec)
| ECase -- Case expressions
(Expr a) -- Expression to scrutinise
[Alter a] -- Alternatives
| ELam [a] (Expr a) -- Lambda abstractions
deriving Show
type ScDef a = (Name, [a], Expr a)
type CoreScDefN = ScDef Name
type Program a = [ScDef a] -- Program is defined polymorphic but will always be Program Name = list of SuperCombinators Name
type CoreProgram = Program Name
type Def a = (a, Expr a) -- for let(rec)
type Alter a = (Int, [a], Expr a) -- for case
data IsRec = NonRecursive | Recursive deriving (Eq, Show)
keywords :: [String]
keywords = ["let", "letrec", "where", "in", "case", "of"]
parseProg :: Parser (Program Name)
parseProg = do p <- parseScDef
do character ';'
ps <- parseProg
return (p:ps)
<|> return [p]
parseScDef :: Parser (ScDef Name)
parseScDef = do v <- identifier
pf <- many identifier
character '='
body <- parseExpr
return (v, pf, body)
parseExpr :: Parser (Expr Name)
parseExpr = do parseLet
<|> do parseCase
<|> do parseLambda
<|> do parseExpr1
parseLet :: Parser (Expr Name)
parseLet = do rc <- isRec
defs <- parseDefs
symbol "in"
ELet rc defs <$> parseExpr
parseCase :: Parser (Expr Name)
parseCase = do symbol "case"
expr <- parseExpr
symbol "of"
ECase expr <$> parseAlts
parseLambda :: Parser (Expr Name)
parseLambda = do character '\\'
vars <- some identifier
character '.'
ELam vars <$> parseExpr
parseAExpr :: Parser (Expr Name)
parseAExpr = do parseVar
<|> do parseNum
<|> do parseConstr
<|> do parsePar
parseNum :: Parser (Expr Name )
parseNum = do ENum <$> integer
parseConstr :: Parser (Expr Name)
parseConstr = do symbol "Pack"
character '{'
tag <- natural
character ','
arity <- natural
character '}'
return (EConstr tag arity)
parsePar :: Parser (Expr Name)
parsePar = do character '('
expr <- parseExpr
character ')'
return expr
parseVar :: Parser (Expr Name)
parseVar = do var <- identifier
if var `notElem` keywords
then return (EVar var)
else empty
isRec :: Parser IsRec
isRec = do prefix <- symbol "let"
do suffix <- symbol "rec"
return Recursive
<|> return NonRecursive
parseDefs :: Parser [Def Name]
parseDefs = do def <- parseDef
do character ';'
defs <- parseDefs
return (def:defs)
<|> return [def]
parseDef :: Parser (Def Name)
parseDef = do id <- identifier
character '='
expr <- parseExpr
return (id, expr)
parseAlts :: Parser [Alter Name]
parseAlts = do alt1 <- parseAlt
do character ';'
alts <- parseAlts
return (alt1:alts)
<|> return [alt1]
parseAlt :: Parser (Alter Name)
parseAlt = do character '<'
n <- natural
character '>'
vars <- many identifier
symbol "->"
expr <- parseExpr
return (n, vars, expr)
parseExpr1 :: Parser (Expr Name)
parseExpr1 = do expr2 <- parseExpr2
do character '|'
compose (EVar "|") expr2 <$> parseExpr1
<|> return expr2
parseExpr2 :: Parser (Expr Name)
parseExpr2 = do expr3 <- parseExpr3
do character '&'
compose (EVar "&") expr3 <$> parseExpr2
<|> return expr3
parseExpr3 :: Parser (Expr Name)
parseExpr3 = do expr4 <- parseExpr4
rel <- relop
compose (EVar rel) expr4 <$> parseExpr4
<|> do parseExpr4
parseExpr4 :: Parser (Expr Name)
parseExpr4 = do expr5 <- parseExpr5
do character '+'
compose (EVar "+") expr5 <$> parseExpr4
<|> do character '-'
compose (EVar "-") expr5 <$> parseExpr5
<|> return expr5
parseExpr5 :: Parser (Expr Name)
parseExpr5 = do expr6 <- parseExpr6
do character '*'
compose (EVar "*") expr6 <$> parseExpr5
<|> do character '/'
compose (EVar "/") expr6 <$> parseExpr6
<|> return expr6
parseExpr6 :: Parser (Expr Name)
parseExpr6 = do exprs <- some parseAExpr
return (foldl1 EAp exprs)
compose :: Expr a -> Expr a -> Expr a -> Expr a
compose expr1 expr2 = EAp (EAp expr1 expr2)