/
Parse.purs
153 lines (127 loc) · 3.77 KB
/
Parse.purs
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
module Lambs.Parse (parseTop) where
import Data.Array as Array
import Data.Set as Set
import Control.Alt ((<|>))
import Control.Lazy (fix)
import Data.Either (Either(..))
import Data.List (List(..), foldl, many, (:))
import Data.Maybe (Maybe(..))
import Data.String (fromCharArray)
import Lambs.Define (Define(..), Undefine(..))
import Lambs.Term (Term(..))
import Lambs.Toplevel (Toplevel(..))
import Prelude (class Monad, Unit, bind, pure, unit, (*), (+), (/=), (<<<), (>>=), not)
import Text.Parsing.Parser (Parser, ParserT, fail, runParser)
import Text.Parsing.Parser.Combinators (between, optional)
import Text.Parsing.Parser.String (class StringLike, eof, satisfy, string)
import Text.Parsing.Parser.Token (letter)
c :: forall a b.a -> b -> Parser String a
c n _ = pure n
reserved :: Set.Set Char
reserved = Set.fromFoldable [':', '\\', '≜', 'λ', ' ', '\n', '\t', '.', '(', ')']
many1 :: forall a b. Parser a b -> Parser a (List b)
many1 p = many p >>= halp
where
halp Nil = fail "oh no"
halp l = pure l
listString :: List Char -> String
listString l = fromCharArray (Array.fromFoldable l)
identifier :: Parser String String
identifier = many1 (satisfy (\x -> not (Set.member x reserved))) >>= pure <<< listString
letters :: Parser String String
letters = many1 letter >>= pure <<< listString
digit :: Parser String Int
digit =
(string "0" >>= c 0)
<|> (string "1" >>= c 1)
<|> (string "2" >>= c 2)
<|> (string "3" >>= c 3)
<|> (string "4" >>= c 4)
<|> (string "5" >>= c 5)
<|> (string "6" >>= c 6)
<|> (string "7" >>= c 7)
<|> (string "8" >>= c 8)
<|> (string "9" >>= c 9)
number :: Parser String Int
number = many1 digit >>= (\l -> pure (foldl (\res n -> n + (res * 10)) 0 l))
lam :: Parser String Term -> Parser String Term
lam x = do
_ <- (string "λ") <|> (string "\\")
p <- identifier
_ <- (string ".")
b <- x
pure (Lam p b)
var :: Parser String Term
var = identifier >>= pure <<< Var
whiteChar :: Parser String Unit
whiteChar = (string " " <|> string "\t" <|> string "\n") >>= c unit
white :: Parser String Unit
white = many whiteChar >>= c unit
white1 :: Parser String Unit
white1 = many1 whiteChar >>= c unit
notApp :: Parser String Term -> Parser String Term
notApp x = paren x <|> lam x <|> var
exp :: Parser String Term
exp = fix (\self -> many (notAppW self) >>= applify)
where
notAppW ex = do
t <- notApp ex
_ <- white
pure t
applify Nil = fail "want more than zero expressions :("
applify (hd : tl) = pure (foldl App hd tl)
paren :: forall a b m.StringLike a => Monad m => ParserT a m b -> ParserT a m b
paren x = between (string "(") (string ")") x
term :: Parser String Term
term = do
x <- exp
_ <- white
_ <- eof
pure x
def :: Parser String Define
def = do
_ <- white
name <- identifier
_ <- white
_ <- string "≜" <|> string ":="
_ <- white
t <- term
pure (Define name t)
undef :: Parser String Undefine
undef = do
_ <- white
name <- identifier
_ <- white
_ <- string "≜" <|> string ":="
_ <- white
_ <- optional (string ":(")
_ <- white
_ <- eof
pure (Undefine name)
run :: forall a b. (Parser a b) -> a -> Maybe b
run p x =
case runParser x p of
Right y -> Just y
Left y -> Nothing
parse :: String -> Maybe Term
parse = run term
-- | Parses a toplevel thing.
parseTop :: String -> Maybe Toplevel
parseTop str =
case run undef s of
Just u -> Just (Undef u)
Nothing ->
case run def s of
Just d -> Just (Def d)
Nothing ->
case run term s of
Just t -> Just (Trm t)
Nothing -> Nothing
where s = removeComment str
removeComment :: String -> String
removeComment s =
case runParser s remove of
Left _ -> s
Right res -> res
where
remove = many (satisfy (\x -> x /= '|')) >>= (\l -> pure (listString l))