|
2 | 2 | {-# LANGUAGE OverloadedStrings #-}
|
3 | 3 | module Parse() where
|
4 | 4 |
|
5 |
| -import Prelude hiding (map) |
6 | 5 | import Data.Char(isSpace)
|
7 | 6 | import qualified Syntax
|
8 | 7 | import qualified Data.Maybe as Maybe
|
9 | 8 | import Data.Function((&))
|
| 9 | +import Control.Applicative(Alternative, (<|>)) |
10 | 10 | import qualified Data.ByteString.Char8 as B
|
11 | 11 |
|
12 |
| -type Parser a |
13 |
| - = B.ByteString -> Maybe (a, B.ByteString) |
| 12 | +newtype Parser a = |
| 13 | + Parser { runParser :: B.ByteString -> Maybe (a, B.ByteString) } |
| 14 | + |
| 15 | +instance Functor Parser where |
| 16 | + fmap f (Parser parser) = |
| 17 | + Parser $ \input -> |
| 18 | + case parser input of |
| 19 | + Nothing -> Nothing |
| 20 | + Just (a, remainder) -> Just (f a, remainder) |
| 21 | + |
| 22 | +instance Applicative Parser where |
| 23 | + pure x = |
| 24 | + Parser $ \input -> |
| 25 | + Just (x, input) |
| 26 | + |
| 27 | + (Parser pFunc) <*> (Parser pArg) = |
| 28 | + Parser $ \input -> do |
| 29 | + (func, remainder1) <- pFunc input |
| 30 | + (arg, remainder2) <- pArg remainder1 |
| 31 | + return (func arg, remainder2) |
| 32 | + |
| 33 | +instance Alternative Parser where |
| 34 | + (Parser p1) <|> (Parser p2) = |
| 35 | + Parser $ \input -> |
| 36 | + (p1 input) <|> (p2 input) |
14 | 37 |
|
15 | 38 | loc :: Syntax.Location
|
16 | 39 | loc = Syntax.Location 0
|
17 | 40 |
|
18 | 41 | string :: B.ByteString -> Parser ()
|
19 | 42 | string str =
|
20 |
| - \input -> |
| 43 | + Parser $ \input -> |
21 | 44 | case B.stripPrefix str input of
|
22 | 45 | Nothing -> Nothing
|
23 | 46 | Just remainder -> Just ((), remainder)
|
24 | 47 |
|
25 |
| -oneOf :: [Parser a] -> Parser a |
26 |
| -oneOf parsers = |
27 |
| - \input -> |
28 |
| - parsers |
29 |
| - & Maybe.mapMaybe ($ input) |
30 |
| - & Maybe.listToMaybe |
31 |
| - |
32 |
| -bind :: Parser a -> (a -> Parser b) -> Parser b |
33 |
| -bind parser f = |
34 |
| - \input -> |
35 |
| - case parser input of |
36 |
| - Nothing -> Nothing |
37 |
| - Just (a, remainder) -> |
38 |
| - (f a) remainder |
39 |
| - |
40 |
| -map :: (a -> b) -> Parser a -> Parser b |
41 |
| -map f parser = |
42 |
| - \input -> |
43 |
| - case parser input of |
44 |
| - Nothing -> Nothing |
45 |
| - Just (a, remainder) -> |
46 |
| - Just (f a, remainder) |
47 |
| - |
48 |
| -unit :: a -> Parser a |
49 |
| -unit a = |
50 |
| - \input -> Just (a, input) |
51 |
| - |
52 | 48 | whitespace :: Parser ()
|
53 | 49 | whitespace =
|
54 |
| - \input -> |
| 50 | + Parser $ \input -> |
55 | 51 | let
|
56 | 52 | (spaces, remainder) = B.span isSpace input
|
57 | 53 | in
|
58 |
| - if B.null spaces then Nothing else Just ((), remainder) |
| 54 | + if B.null spaces |
| 55 | + then Nothing |
| 56 | + else Just ((), remainder) |
59 | 57 |
|
60 | 58 | term :: Parser Syntax.Term
|
61 | 59 | term =
|
62 |
| - oneOf |
63 |
| - [ literalTrue |
64 |
| - , literalFalse |
65 |
| - , if_ |
66 |
| - ] |
| 60 | + literalTrue |
| 61 | + <|> literalFalse |
| 62 | + <|> if_ |
67 | 63 |
|
68 | 64 | literalTrue :: Parser Syntax.Term
|
69 | 65 | literalTrue =
|
70 |
| - map (const $ Syntax.True_ loc) (string "true") |
| 66 | + fmap (const $ Syntax.True_ loc) (string "true") |
71 | 67 |
|
72 | 68 | literalFalse :: Parser Syntax.Term
|
73 | 69 | literalFalse =
|
74 |
| - map (const $ Syntax.False_ loc) (string "false") |
| 70 | + fmap (const $ Syntax.False_ loc) (string "false") |
75 | 71 |
|
76 | 72 | if_ :: Parser Syntax.Term
|
77 | 73 | if_ =
|
78 |
| - string "if" `bind` \_ -> |
79 |
| - whitespace `bind` \_ -> |
80 |
| - term `bind` \condTerm -> |
81 |
| - whitespace `bind` \_ -> |
82 |
| - string "then" `bind` \_ -> |
83 |
| - whitespace `bind` \_ -> |
84 |
| - term `bind` \thenTerm -> |
85 |
| - whitespace `bind` \_ -> |
86 |
| - string "else" `bind` \_ -> |
87 |
| - whitespace `bind` \_ -> |
88 |
| - term `bind` \elseTerm -> |
89 |
| - unit (Syntax.If loc condTerm thenTerm elseTerm) |
| 74 | + let |
| 75 | + f _ _ condTerm _ _ _ thenTerm _ _ _ elseTerm = |
| 76 | + Syntax.If loc condTerm thenTerm elseTerm |
| 77 | + in |
| 78 | + f |
| 79 | + <$> string "if" |
| 80 | + <*> whitespace |
| 81 | + <*> term |
| 82 | + <*> whitespace |
| 83 | + <*> string "then" |
| 84 | + <*> whitespace |
| 85 | + <*> term |
| 86 | + <*> whitespace |
| 87 | + <*> string "else" |
| 88 | + <*> whitespace |
| 89 | + <*> term |
0 commit comments