-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathDecl.hs
67 lines (59 loc) · 1.7 KB
/
Decl.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
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}
{-# LANGUAGE RecordWildCards, OverloadedStrings #-}
module Toy.Language.Parser.Decl
( funSig
, funDef
, funDefNamed
) where
import Control.Monad.Combinators.Expr
import Data.Functor
import Data.Tuple.Extra
import Text.Megaparsec
import Text.Megaparsec.Char.Lexer hiding(binary)
import Toy.Language.Parser.Common
import Toy.Language.Parser.Ty
import Toy.Language.Parser.Util
import Toy.Language.Syntax.Decls
import Toy.Language.Syntax.Terms
funSig :: ToyMonad e s m => m FunSig
funSig = do
funName <- lexeme' identifier
void $ lsymbol ":"
funTy <- ty
pure FunSig { .. }
funDef :: ToyMonad e s m => m FunDef
funDef = funDefNamed identifier
funDefNamed :: ToyMonad e s m => m String -> m FunDef
funDefNamed funNameParser = do
funName <- lexeme' funNameParser
funArgs <- many varName
void $ lstring "="
funBody <- term
pure FunDef { .. }
term :: ToyMonad e s m => m Term
term = makeExprParser tapps table
where
tapps = foldl1 (TApp ()) <$> atom `sepBy1` lexSpace
atom = choice $ try <$> subAtoms
subAtoms = [ TName () <$> varName
, TInteger () <$> lexeme' decimal
, uncurry3 (TIfThenElse ()) <$> tIfThenElse
, parens term
]
table = [ [ binary "+" BinOpPlus
, binary "-" BinOpMinus
]
, [ binary ">" BinOpGt
, binary "<" BinOpLt
]
]
binary name fun = InfixL $ lstring name $> (\a b -> TBinOp () a fun b)
tIfThenElse :: ToyMonad e s m => m (Term, Term, Term)
tIfThenElse = do
void $ lstring "if"
tcond <- term
void $ lstring "then"
tthen <- term
void $ lstring "else"
telse <- term
pure (tcond, tthen, telse)