View difference between Paste ID: FQispXuc and 8a1aEgh6
SHOW: | | - or go back to the newest paste.
1
{- CIS 194 HW 11
2
   due Monday, 8 April
3
-}
4
5
module Week11.SExpr where
6
7
import Week11.AParser
8
import Control.Applicative
9
10
import Data.Char(isSpace, isAlpha, isAlphaNum)
11
12
------------------------------------------------------------
13
--  1. Parsing repetitions
14
------------------------------------------------------------
15
16
zeroOrMore :: Parser a -> Parser [a]
17
zeroOrMore p = many_v
18
    where many_v = some_v <|> pure []
19
          some_v = (:) <$> p <*> many_v
20
21
oneOrMore :: Parser a -> Parser [a]
22
oneOrMore p = some_v
23
    where many_v = some_v <|> pure []
24
          some_v = (:) <$> p <*> many_v
25
26
------------------------------------------------------------
27
--  2. Utilities
28
------------------------------------------------------------
29
30
spaces :: Parser String
31
spaces = zeroOrMore (satisfy isSpace)
32
33
ident :: Parser String
34
ident = (:) <$> satisfy isAlpha <*> zeroOrMore (satisfy isAlphaNum)
35
36
------------------------------------------------------------
37
--  3. Parsing S-expressions
38
------------------------------------------------------------
39
40
-- An "identifier" is represented as just a String; however, only
41
-- those Strings consisting of a letter followed by any number of
42
-- letters and digits are valid identifiers.
43
type Ident = String
44
45
-- An "atom" is either an integer value or an identifier.
46
data Atom = N Integer | I Ident
47
  deriving Show
48
49
-- An S-expression is either an atom, or a list of S-expressions.
50
data SExpr = A Atom
51
           | Comb [SExpr]
52
  deriving Show
53
54
parseAtom :: Parser Atom
55
parseAtom = ( N <$> (spaces *> posInt)) <|> ( I <$> (spaces *> ident))
56
57
58
parseSExpr :: Parser SExpr
59
parseSExpr = (A <$> parseAtom) <|> Comb <$> (spaces *> char '(' *> oneOrMore (parseSExpr) <* spaces <* char ')')