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
|
module Parser where
import Ast
import Data.Maybe (isJust)
import Lexer
import Text.Parsec
import qualified Text.Parsec.Expr as E
import Text.Parsec.String (Parser)
binary s f assoc = E.Infix (reservedOp s >> return (BinOp f)) assoc
opTable =
[ [ binary "*" Mul E.AssocLeft,
binary "/" Div E.AssocLeft
],
[ binary "+" Plus E.AssocLeft,
binary "-" Minus E.AssocLeft
]
]
expr :: Parser Expr
expr = E.buildExpressionParser opTable factor
number :: Parser Expr
number = do
pos <- getPosition
n <- integer
return $ Num n pos
true :: Parser Expr
true = do
pos <- getPosition
reserved "true"
return $ Bool' True pos
false :: Parser Expr
false = do
pos <- getPosition
reserved "false"
return $ Bool' False pos
variable :: Parser Expr
variable = do
pos <- getPosition
var <- identifier
return $ Variable var pos
typ :: Parser Type
typ = do
p <- identifier
return $ Type p
typFn :: Parser Type
typFn = do
p <- parens $ commaSep typ
r <- optionMaybe $ do
reserved "->"
typ
return $ FuncType p r
type' :: Parser Type
type' = do
try typFn
<|> typ <?> "type"
arg :: Parser (String, Type, Bool, SourcePos)
arg = do
pos <- getPosition
i <- identifier
_ <- colonSep <?> "\":\" before type"
t <- type' <?> "type"
return $ (i, t, True, pos)
fdef :: Ident -> Bool -> Bool -> SourcePos -> Parser Expr
fdef ident priv anon pos = do
args <- parens $ commaSep arg
rtyp <-
optionMaybe
( do
_ <- colonSep <?> "\":\" before type"
rtyp <- type' <?> "return type"
return $ rtyp
)
body <- braces $ many statement
return $ Func ident args rtyp body priv anon pos
function :: Bool -> Parser Expr
function priv = do
pos <- getPosition
reserved "def"
ident <- identifier
fdef ident priv False pos
var :: Bool -> Parser Expr
var priv = do
reserved "var"
(ident, typ, _, pos) <- arg
reservedOp "=" <?> "assignation"
value <- expr
reservedOp ";"
return $ Var ident typ value priv pos
privateDfn :: Parser Expr
privateDfn = do
priv <- optionMaybe $ reserved "private"
let isPriv = isJust priv
try (function isPriv) <|> var isPriv
lambdaId :: SourcePos -> Ident
lambdaId s =
"lambda" ++ "@" ++ show (sourceLine s) ++ "," ++ show (sourceColumn s)
lambda :: Parser Expr
lambda = do
pos <- getPosition
fdef (lambdaId pos) True True pos
return' :: Parser Expr
return' = do
pos <- getPosition
reserved "return"
value <- optionMaybe expr
reservedOp ";"
return $ Return value pos
call :: Parser Expr
call = do
pos <- getPosition
ident <- try lambda <|> variable
args <- parens $ commaSep expr
return $ Call ident args pos
factor :: Parser Expr
factor =
number
<|> true
<|> false
<|> try call
<|> try lambda
<|> try variable
<|> parens expr
exprStmt :: Parser Expr
exprStmt = do
e <- expr <|> factor
reservedOp ";"
return $ e
statement :: Parser Expr
statement = do
try exprStmt
<|> var False
<|> return'
module' :: Parser Expr
module' = do
pos <- getPosition
reserved "module"
ident <- identifier
return $ Module ident pos
program :: Parser [Expr]
program = do
m <- module'
n <- many $ do privateDfn <|> statement
return $ [m] ++ n
parse :: Parser [Expr]
parse = program
parseFromFile p fname = do
input <- readFile fname
return (runParser p () fname input)
|