-
Notifications
You must be signed in to change notification settings - Fork 1
/
Parser.hs
325 lines (288 loc) · 8.62 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
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
module Parser (ParserLib.Error(..), parseSPL) where
import ParserLib
import qualified Source (IndexSpan)
import qualified Lexer
import qualified AST
import Meta
parseSPL :: [Lexer.Token] -> Either [P1 AST.Program] Error
parseSPL tokens = parse parseProgram tokens
parseProgram :: ParseFuncD (P1 AST.Program)
parseProgram = newObject $ do
decls <- many1 parseDecl
produceP1 $ AST.Program decls
parseDecl :: ParseFuncD (P1 AST.Decl)
parseDecl = parseExternDecl <|> parseVarDecl <|> parseFunDecl
parseExternDecl :: ParseFuncD (P1 AST.Decl)
parseExternDecl = newObject $ do
equalsToken Lexer.Extern
l <- parseLanguage
t <- parseVoidType <!> parseType
i <- parseIdentifier
equalsToken Lexer.ParenthesesOpen
fargs <- parseFargs
equalsToken Lexer.ParenthesesClose
equalsToken Lexer.Semicolon
produceP1 $ AST.ExternDecl l t i fargs
parseLanguage :: ParseFuncD (P1 AST.ExternLanguage)
parseLanguage = newObject $ do
(Lexer.QuotedString str) <- parseToken (\t -> case t of
Lexer.QuotedString _ -> True
_ -> False)
produceP1 $ AST.ExternLanguage str
parseVarDecl :: ParseFuncD (P1 AST.Decl)
parseVarDecl = newObject $ do
t <- parseType
i <- parseIdentifier
equalsToken Lexer.AssignmentSign
e <- parseExpr
equalsToken Lexer.Semicolon
produceP1 $ AST.VarDecl t i e
parseFunDecl :: ParseFuncD (P1 AST.Decl)
parseFunDecl = newObject $ do
exp <- opt $ equalsToken Lexer.Export
t <- parseVoidType <!> parseType
i <- parseIdentifier
equalsToken Lexer.ParenthesesOpen
fargs <- parseFargs
equalsToken Lexer.ParenthesesClose
equalsToken Lexer.CurlyBracketOpen
vdecls <- many parseVarDecl
stmts <- many1 parseStmt
equalsToken Lexer.CurlyBracketClose
let attributes = case exp of
Nothing -> []
Just _ -> [AST.Export]
produceP1 $ AST.FunDecl t i fargs vdecls stmts attributes
parseFarg :: ParseFuncD (P1 AST.Type, P1 AST.Identifier)
parseFarg = do
t <- parseType
i <- parseIdentifier
return (t, i)
parseFargs :: ParseFuncD [(P1 AST.Type, P1 AST.Identifier)]
parseFargs = manyd parseFarg (equalsToken Lexer.Comma)
parseStmt :: ParseFuncD (P1 AST.Stmt)
parseStmt = newObject $
do
equalsToken Lexer.CurlyBracketOpen
stmts <- many parseStmt
equalsToken Lexer.CurlyBracketClose
produceP1 $ AST.Scope stmts
<|> do
equalsToken Lexer.If
equalsToken Lexer.ParenthesesOpen
expr <- parseExpr
equalsToken Lexer.ParenthesesClose
stmt <- parseStmt
produceP1 $ AST.If expr stmt
<|> do
equalsToken Lexer.If
equalsToken Lexer.ParenthesesOpen
expr <- parseExpr
equalsToken Lexer.ParenthesesClose
tstmt <- parseStmt
equalsToken Lexer.Else
estmt <- parseStmt
produceP1 $ AST.IfElse expr tstmt estmt
<|> do
equalsToken Lexer.While
equalsToken Lexer.ParenthesesOpen
expr <- parseExpr
equalsToken Lexer.ParenthesesClose
stmt <- parseStmt
produceP1 $ AST.While expr stmt
<|> do
i <- parseIdentifier
equalsToken Lexer.AssignmentSign
expr <- parseExpr
equalsToken Lexer.Semicolon
produceP1 $ AST.Assignment i expr
<|> do
equalsToken Lexer.Return
expr <- opt parseExpr
equalsToken Lexer.Semicolon
produceP1 $ AST.Return expr
<|> do
expr <- parseExpr
equalsToken Lexer.Semicolon
produceP1 $ AST.Expr expr
parseExpr :: ParseFuncD (P1 AST.Expr)
parseExpr = parseTerm0
parseTerm0 :: ParseFuncD (P1 AST.Expr)
parseTerm0 = newObject $ do
expr1 <- parseTerm1
do
b <- parseOp2Bool
expr2 <- parseTerm0
produceP1 $ AST.Binop expr1 b expr2
<!> passthrough expr1
parseTerm1 :: ParseFuncD (P1 AST.Expr)
parseTerm1 = newObject $ do
expr1 <- parseTerm2
do
b <- parseOp2Equal
expr2 <- parseTerm1
produceP1 $ AST.Binop expr1 b expr2
<!> passthrough expr1
parseTerm2 :: ParseFuncD (P1 AST.Expr)
parseTerm2 = parseTerm3
<!> do newObject $ do
b <- parseOpNot
expr <- parseTerm2
produceP1 $ AST.Unop b expr
parseTerm3 :: ParseFuncD (P1 AST.Expr)
parseTerm3 = newObject $ do
e1 <- parseTerm4
do
b <- parseOp2Cons
e2 <- parseTerm3
produceP1 $ AST.Binop e1 b e2
<!> passthrough e1
parseTerm4 :: ParseFuncD (P1 AST.Expr)
parseTerm4 = newObjectd $ do
e <- parseTerm5
parseTerm4b e
parseTerm4b :: (P1 AST.Expr) -> ParseFuncD (Source.IndexSpan -> ParseFuncD (P1 AST.Expr))
parseTerm4b e1 =
do b <- parseOp2Add
return $ \l -> newObjectd $ do
e2 <- parseTerm5
f <- produceP1 $ AST.Binop e1 b e2
parseTerm4b $ f l
<!> do
passthrough $ return e1
parseTerm5 :: ParseFuncD (P1 AST.Expr)
parseTerm5 = newObjectd $ do
e <- parseTerm6
parseTerm5b e
parseTerm5b :: (P1 AST.Expr) -> ParseFuncD (Source.IndexSpan -> ParseFuncD (P1 AST.Expr))
parseTerm5b e1 =
do b <- parseOp2Mult
return $ \l -> newObjectd $ do
e2 <- parseTerm6
f <- produceP1 $ AST.Binop e1 b e2
parseTerm5b $ f l
<!> do
passthrough $ return e1
parseTerm6 :: ParseFuncD (P1 AST.Expr)
parseTerm6 = parseTerm7
<!> do newObject $ do
b <- parseOpNegative
e <- parseTerm6
produceP1 $ AST.Unop b e
parseTerm7 :: ParseFuncD (P1 AST.Expr)
parseTerm7 = newObject $
do
n <- parseInteger
produceP1 $ AST.Kint n
<!> do
equalsToken Lexer.ParenthesesOpen
e1 <- parseExpr
do
equalsToken Lexer.ParenthesesClose
passthrough e1
<!> do
equalsToken Lexer.Comma
e2 <- parseExpr
equalsToken Lexer.ParenthesesClose
produceP1 $ AST.Pair e1 e2
<!> do equalsToken Lexer.TrueT
produceP1 $ AST.Kbool True
<!> do equalsToken Lexer.FalseT
produceP1 $ AST.Kbool False
<!> do
i <- parseIdentifier
produceP1 $ AST.Var i
<|> do
i <- parseIdentifier
equalsToken Lexer.ParenthesesOpen
args <- parseActArgs
equalsToken Lexer.ParenthesesClose
produceP1 $ AST.FunCall i args
<!> do equalsToken Lexer.SquareBracketsOpen
equalsToken Lexer.SquareBracketsClose
produceP1 AST.Nil
parseActArgs :: ParseFuncD [P1 AST.Expr]
parseActArgs = manyd parseExpr (equalsToken Lexer.Comma)
parseVoidType :: ParseFuncD (P1 AST.Type)
parseVoidType = parseOne $ \x -> case x of
Lexer.Token (Lexer.Type t) l -> case t of
Lexer.Void -> Just $ AST.Void $ constructP1 l
_ -> Nothing
_ -> Nothing
parseBasicType :: ParseFuncD (P1 AST.Type)
parseBasicType = parseOne $ \x -> case x of
Lexer.Token (Lexer.Type t) l -> case t of
Lexer.Int -> Just $ AST.Int (constructP1 l)
Lexer.Bool -> Just $ AST.Bool (constructP1 l)
_ -> Nothing
_ -> Nothing
parseType :: ParseFuncD (P1 AST.Type)
parseType = newObject $
do t <- parseBasicType
passthrough t
<|> do
equalsToken Lexer.ParenthesesOpen
t1 <- parseType
equalsToken Lexer.Comma
t2 <- parseType
equalsToken Lexer.ParenthesesClose
produceP1 (AST.Product t1 t2)
<|> do
equalsToken Lexer.SquareBracketsOpen
t <- parseType
equalsToken Lexer.SquareBracketsClose
produceP1 (AST.ListType t)
<|> do
i <- parseIdentifier
produceP1 (AST.TypeIdentifier i)
operatorToken :: (Lexer.OperatorE -> Maybe (P1Meta -> a)) -> ParseFuncD a
operatorToken f = parseOne $ \t -> case t of
Lexer.Token (Lexer.Operator op) l -> case f op of
Just x -> Just (x (constructP1 l))
Nothing -> Nothing
_ -> Nothing
parseOp2Mult :: ParseFuncD (P1 AST.BinaryOperator)
parseOp2Mult = operatorToken $ \op -> case op of
Lexer.Multiplication -> Just AST.Multiplication
Lexer.Division -> Just AST.Division
Lexer.Modulo -> Just AST.Modulo
_ -> Nothing
parseOp2Add :: ParseFuncD (P1 AST.BinaryOperator)
parseOp2Add = operatorToken $ \op -> case op of
Lexer.Plus -> Just AST.Plus
Lexer.Minus -> Just AST.Minus
_ -> Nothing
parseOp2Cons :: ParseFuncD (P1 AST.BinaryOperator)
parseOp2Cons = operatorToken $ \op -> case op of
Lexer.Cons -> Just AST.Cons
_ -> Nothing
parseOp2Equal :: ParseFuncD (P1 AST.BinaryOperator)
parseOp2Equal = operatorToken $ \op -> case op of
Lexer.Equals -> Just AST.Equals
Lexer.LesserThan -> Just AST.LesserThan
Lexer.GreaterThan -> Just AST.GreaterThan
Lexer.LesserEqualThan -> Just AST.LesserEqualThan
Lexer.GreaterEqualThan -> Just AST.GreaterEqualThan
Lexer.Nequals -> Just AST.Nequals
_ -> Nothing
parseOp2Bool :: ParseFuncD (P1 AST.BinaryOperator)
parseOp2Bool = operatorToken $ \op -> case op of
Lexer.And -> Just AST.And
Lexer.Or -> Just AST.Or
_ -> Nothing
parseOpNot :: ParseFuncD (P1 AST.UnaryOperator)
parseOpNot = operatorToken $ \op -> case op of
Lexer.Not -> Just AST.Not
_ -> Nothing
parseOpNegative :: ParseFuncD (P1 AST.UnaryOperator)
parseOpNegative = operatorToken $ \op -> case op of
Lexer.Minus -> Just AST.Negative
_ -> Nothing
parseIdentifier :: ParseFuncD (P1 AST.Identifier)
parseIdentifier = parseOne $ \x -> case x of
(Lexer.Token (Lexer.Identifier str) l) -> Just (AST.Identifier str Nothing (AST.IdentInfo {}) (constructP1 l))
_ -> Nothing
parseInteger :: ParseFuncD AST.Integer
parseInteger = parseOne $ \x -> case x of
(Lexer.Token (Lexer.Integer n) _) -> Just n
_ -> Nothing