-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParse.hs
40 lines (31 loc) · 1.36 KB
/
Parse.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
module Parse where
import Text.ParserCombinators.Parsec
import Data.Char (isSpace, isDigit, isLetter)
import Piless
pa <^> pb = pa <* notCode <*> pb
pa ^> pb = (pa >> notCode) *> pb
pa <^ pb = pa <* (notCode >> pb)
infixl 4 <^>, <^, ^>
comment = char '#' >> skipMany (noneOf "\n") >> char '\n'
notCode = ((comment <|> space) >> notCode) <|> return ()
word :: Parser String
word = many1 $ satisfy isLetter
decim :: Parser Int
decim = read <$> many1 digit
parseProgram :: String -> Term
parseProgram s = parseSource lc s
parseSource :: Parser Term -> String -> Term
parseSource p src = either (error.show) id . parse p "" $ src
parseFile :: String -> IO Term
parseFile s = parseProgram <$> readFile s
lc :: Parser Term
lc = Lam <$> ((char '\\' <|> char 'λ') ^> (word <^ char ':')) <^> (lc <^ char '.') <^> lc
<|> Pi <$> (char '∀' ^> (word <^ char ':')) <^> (lc <^ char ',') <^> lc
<|> Type . toEnum . const 0 <$> (char '*') -- ^> decim)
<|> Var <$> word
<|> char '(' ^> (foldl1 App <$> many1 (notCode *> lc <* notCode)) <^ char ')'
<|> char '[' ^> (foldr1 App <$> many1 (notCode *> lc <* notCode)) <^ char ']'
<|> char '{' ^> (lets <$> many (notCode *> binding <* notCode) <^> (char '}' ^> lc))
where lets = flip $ foldr ($)
binding = mylet <$> word <^> (char ':' ^> lc) <^> (char '=' ^> lc)
mylet var ty term body = App (Lam var ty body) term