-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathParser.hs
237 lines (196 loc) · 6.01 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
module Parser
( parseString
, parseFile
, parseExpression
, wrapSpace
) where
{-
It always makes me so happy,
when you find someone alive.
- Alaska State Troopers S4 E16
-}
---- Format Import
import Data.Char
import Main.Utf8 (withUtf8)
---- Parsec Import
import Text.ParserCombinators.Parsec
---- Language Import
import ErrorHandler
import Encoding
import Config
import Lexer
import AST
---- Helpers
-- there probably is a function that does this... right?
wrapSpace func = do
whiteSpace
f <- func
whiteSpace
return f
---- Statement Parser
whileParser :: Parser Sequence
whileParser = do
whiteSpace
ld <- whileIDSL <|> return [] -- FIXME no mult. IDSLs
s <- concat <$> manyTill sequentStatement eof
return $ ld ++ s
sequentStatement :: Parser [Stmt]
sequentStatement = wrapSpace statement
statement :: Parser [Stmt]
statement = try assignStmt
<|> fmap (:[]) expressStmt
expressStmt :: Parser Stmt
expressStmt = Express <$> expression
assignStmt :: Parser [Stmt]
assignStmt = do
var <- sepBy identifier comma
reservedOp ":="
expr <- expression
spaces
arity <- getArity expr <|> countArity expr
return $ map (\n -> Assign n expr arity) var
countArity :: Bλ -> Parser Integer
countArity = return . countLambda
getArity :: Bλ -> Parser Integer
getArity expr = do
fullArity <- countArity expr
reservedOp "::"
arity <- natural
if (arity > fullArity) && Config.arityBlock then
failWith "Parse Error\narity cannot be higher than the number of binders"
else
return arity
---- Isolated DSL parser (IDSL)
whileIDSL :: Parser Sequence
whileIDSL = whileLangDef
---- Language Definiton Statement Parser
whileLangDef :: Parser Sequence
whileLangDef = string "{!" *> manyTill langdefStmt (string "!}")
langdefStmt :: Parser Stmt
langdefStmt = wrapSpace sequentLangDef
sequentLangDef :: Parser Stmt
sequentLangDef = importLangDef
<|> formatLangDef
importLangDef :: Parser Stmt
importLangDef = do
string "import"
spaces
file <- many1 alphaNum
return $ Import file
formatLangDef :: Parser Stmt
formatLangDef = do
string "format"
spaces
formatter <- many1 (alphaNum <|> oneOf "}{)(")
return $ Assign "__FORMATTER__" (parseExpression formatter) 1
funcExpression :: Parser Bλ
funcExpression = do
name <- identifier
spaces
args <- braces (sepBy (wrapSpace expression) comma) <|> return []
return $ Fun name args
---- Expression Parser
expression :: Parser Bλ
expression = idxExpression
-- <|> try absCommented
<|> absExpression
<|> unevalApp
<|> parens appExpression
<|> synSugar
<|> funcExpression
<|> listParser
idxExpression :: Parser Bλ
idxExpression = Idx <$> natural
absExpression :: Parser Bλ
absExpression = reservedOp "λ" *> (Abs <$> expression)
-- FIXME parses weird
absCommented :: Parser Bλ
absCommented = do
reservedOp "λ"
manyTill letter (notFollowedBy (oneOf "λ."))
char '.';
whiteSpace
Abs <$> expression
unevalApp :: Parser Bλ
unevalApp = do
char '\''
apps <- parens $ sepBy1 expression spaces
return $ foldl1 (App False) apps
appExpression :: Parser Bλ
appExpression = foldl1 (App True) <$> sepBy1 expression spaces
synSugar :: Parser Bλ
synSugar = unlP
<|> prtP
<|> intP
<|> chrP
<|> eqP
unlP, intP, chrP :: Parser Bλ
unlP = try $ string "UNL" *> (Unl <$> braces (many1 (noneOf "}")))
prtP = try $ string "PRT" *> (toPrint <$> braces (many1 (noneOf "}")))
intP = try $ string "INT" *> (encode toInt <$> braces (many1 digit))
chrP = try $ string "CHR" *> (encode ord <$> braces anyChar)
eqP :: Parser Bλ
eqP = try $ string "EQ" *> (Fun "__EQ__" <$> braces (sepBy (wrapSpace expression) comma))
listParser :: Parser Bλ
listParser = try unlL
<|> try intL
<|> try prtL
<|> chrL
<|> listIndex
<|> listP
<|> pairP
unlL :: Parser Bλ
unlL = do
string "UNL"
unls <- brackets (sepBy (many1 $ noneOf "],") comma)
let mapU = map Unl unls
return $ toList mapU
prtL :: Parser Bλ
prtL = do
string "PRT"
prts <- brackets (sepBy (many1 $ noneOf "],") comma)
let mapP = map toPrint prts
return $ toList mapP
intL :: Parser Bλ
intL = do
string "INT"
ints <- brackets (sepBy1 (many1 digit) comma)
let encI = map (encode toInt) ints
return $ toList encI
chrL :: Parser Bλ
chrL = do
char '"'
chrs <- manyTill anyChar (try (string "\""))
let encC = map (encode ord) chrs
return $ toList encC
-- FIXME also parses weird..
-- That is, not at all
listIndex :: Parser Bλ
listIndex = do
name <- identifier
idx <- brackets (many1 digit)
return $ let eI = encode toInt idx
in Fun "get" [eI, Fun name []]
listP :: Parser Bλ
listP = toList <$> brackets (sepBy (wrapSpace expression) comma)
pairP :: Parser Bλ
pairP = toPair <$> angles (sepBy expression comma)
where toPair :: [Bλ] -> Bλ
toPair [a, b] = Fun "pair" [a, b]
toPair _ = failWith "Parse Error\ntoo many elements"
---- User Input, Debug
parseString :: String -> Sequence
parseString str = case parse whileParser "String Parser" str of
Left e -> failWith $ show e
Right r -> r
parseFile :: FilePath -> IO Sequence
parseFile file = withUtf8 $ do
program <- readFile file
case parse whileParser file program of
Left e -> print e >> fail "Parse Error"
Right r -> return r
-- This is really only for debugging and testing purposes
parseExpression :: String -> Bλ
parseExpression str = case parse expression "Expression Parser" str of
Left e -> failWith $ show e
Right r -> r