-
Notifications
You must be signed in to change notification settings - Fork 117
/
Copy pathParse3.hs
162 lines (131 loc) · 3.94 KB
/
Parse3.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
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
import Text.Parsec
import Text.Parsec.Text
--import Text.Parsec.Expr
import qualified Text.Parsec.Token as Tok
import qualified Text.Parsec.Language as Lang
import qualified Data.Text as T
import Data.Functor.Identity (Identity)
lett :: T.Text
lett = "abcdefghijklmnopqrstuvwxyz"
num :: T.Text
num = "1234567890"
lexer :: Tok.GenTokenParser T.Text () Identity
lexer = Tok.makeTokenParser style
style :: Tok.GenLanguageDef T.Text () Identity
style = Lang.emptyDef {
Tok.commentStart = "{-"
, Tok.commentEnd = "-}"
, Tok.identStart = lett <|> oneOf "+-/*"
, Tok.identLetter = lett <|> num <|> oneOf "_'"
, Tok.reservedOpNames = [ "'", "\""]
, Tok.reservedNames = [ "true", "false"
, "let", "quote", "lambda"
, "Nil" ]
}
{-
Tok.TokenParser { parens = m_parens
, identifier = m_identifier -- Tok.Identifer lexer
, reservedOp = m_reservedOp
, reserved = m_reserved
, semiSep1 = m_semiSep1
, whiteSpace = m_whiteSpace } = makeTokenParser style
-}
reservedOp :: T.Text -> Parser ()
reservedOp op = Tok.reservedOp lexer (T.unpack op)
parseAtom :: Parser LispVal
parseAtom = Atom . T.pack <$> Tok.identifier lexer
parseString :: Parser LispVal
parseString =
do reservedOp "\""
p <- Tok.identifier lexer
reservedOp "\""
return $ Str (T.pack p)
parseNumber :: Parser LispVal
parseNumber = fmap (Num . read) $ many1 digit
parseList :: Parser LispVal
parseList = List . concat <$> (many parseExpr `sepBy` char ' ')
{-
parseSExp1 :: Parser LispVal
parseSExp1 = List . concat <$> Tok.parens (many parseExpr `sepBy` char ' ')
-}
parseSExp :: Parser LispVal
parseSExp =
do reservedOp "("
p <- (many parseExpr `sepBy` char ' ')
reservedOp ")"
return $ List . concat $ p
parseQuote :: Parser LispVal
parseQuote =
do
reservedOp "\'"
x <- parseExpr
return $ List [Atom "quote", x]
parseExpr :: Parser LispVal
parseExpr = parseAtom
<|> parseString
<|> parseNumber
<|> parseReserved
<|> parseQuote
<|> parseSExp
parseReserved =
do
reservedOp "Nil" >> return Nil
<|> (reservedOp "#t" >> return (Bin True))
<|> (reservedOp "#f" >> return (Bin False))
contents :: Parser a -> Parser a
contents p = do
Tok.whiteSpace lexer
r <- p
eof
return r
readExpr :: T.Text -> Either ParseError LispVal
readExpr = parse (contents parseExpr) "<stdin>"
-------------------------
-- STAND ALONE TEST
-- --------------------
p pa inp = case parse pa "" inp of
{ Left err -> "err " ++ show err
; Right ans -> "ans " ++ show ans
}
-- need a copy of LispVal for stand alone
data LispVal = Nil | Bin Bool | Atom T.Text | Num Int | Str T.Text | List [LispVal] deriving (Show)
main :: IO ()
main =
do
print $ p parseReserved "Nil"
print $ p parseExpr "Nil"
print $ p parseExpr "'Nil"
print " "
print $ p parseQuote "'(1 2 3 4)"
print $ p parseQuote "'x"
print $ p parseQuote "'()"
print " "
print " "
print $ p (parseExpr) "(1)"
print $ p parseList "a \"a\" \"a\""
print $ p parseList "x 1 2"
print $ p parseSExp "(a \"a\" \"a\")"
print $ p parseSExp "(1 2 3 4)"
print " "
print " "
--print $ p (m_parens (many parseExpr `sepBy` char ' ')) "(lambda (fnName a b c) (body) )"
print $ p parseSExp "(lambda (fnName a b c) (body) )"
print $ p parseSExp "(a 1 b 2)"
print $ p parseSExp "(let (a 1 b 2) (fn a b) )"
print $ p parseSExp "(let (a (x 1 2) b (y 3 4)) (fn a b) )"
print " "
print " "
print $ p parseExpr "x"
print $ p parseExpr "1"
print $ p parseExpr "\"a b c d\""
print $ p parseExpr "(3 1)"
print " "
print $ p parseReserved "#t"
print $ p parseReserved "#f"
print $ p parseExpr "#t"
print $ p parseExpr "#f"
print " "
print $ p parseExpr "(eq? 1 2)"
print $ p parseExpr "1"