Skip to content

Commit 15a5b6c

Browse files
committed
Parser is now a monad transformer
1 parent 2be68f5 commit 15a5b6c

File tree

7 files changed

+140
-99
lines changed

7 files changed

+140
-99
lines changed

Gruntfile.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@ module.exports = function(grunt) {
66

77
clean: ["externs", "js"],
88

9-
"purescript-make": {
9+
"purescript": {
1010
options: {
1111
tco: true,
12+
main: true,
1213
magicDo: true
1314
},
1415
lib: {
1516
src:
1617
[ "src/**/*.purs.hs"
1718
, "examples/**/*.purs.hs"
1819
, "bower_components/purescript-*/src/**/*.purs"
19-
]
20+
],
21+
dest: "js/Main.js"
2022
}
2123
}
2224

@@ -25,5 +27,5 @@ module.exports = function(grunt) {
2527
grunt.loadNpmTasks("grunt-purescript");
2628
grunt.loadNpmTasks("grunt-contrib-clean");
2729

28-
grunt.registerTask("default", ["purescript-make:lib"]);
30+
grunt.registerTask("default", ["purescript:lib"]);
2931
};

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"tmp/**"
88
],
99
"dependencies": {
10-
"purescript-transformers": "https://github.com/purescript/purescript-transformers.git",
10+
"purescript-transformers": "*",
1111
"purescript-either": "*",
1212
"purescript-maybe": "*",
1313
"purescript-arrays": "*",

examples/test.purs.hs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,31 @@ import Data.Array
55
import Data.Either
66
import Data.Maybe
77
import Control.Monad.Eff
8+
import Control.Monad.Identity
89
import Debug.Trace
910
import Text.Parsing.Parser
1011
import Text.Parsing.Parser.Combinators
1112
import Text.Parsing.Parser.Expr
1213
import Text.Parsing.Parser.String
1314

14-
parens :: forall a. ({} -> Parser String a) -> Parser String a
15+
parens :: forall m a. (Monad m) => ({} -> ParserT String m a) -> ParserT String m a
1516
parens = between (string "(") (string ")")
1617

17-
nested :: {} -> Parser String Number
18+
nested :: forall m. (Monad m) => {} -> ParserT String m Number
1819
nested _ = (do
1920
string "a"
2021
return 0) <|> ((+) 1) <$> parens nested
2122

2223
parseTest :: forall s a eff. (Show a) => Parser s a -> s -> Eff (trace :: Trace | eff) {}
23-
parseTest p input = case runParser p input of
24-
ParseResult { result = Left (ParseError err) } -> print err.message
25-
ParseResult { result = Right result } -> print result
24+
parseTest p input = case runParser input p of
25+
Left (ParseError err) -> print err.message
26+
Right result -> print result
2627

28+
opTest :: Parser String String
2729
opTest = chainl char (do string "+"
2830
return (++)) ""
2931

32+
digit :: Parser String Number
3033
digit = (string "0" >>= \_ -> return 0)
3134
<|> (string "1" >>= \_ -> return 1)
3235
<|> (string "2" >>= \_ -> return 2)
@@ -38,6 +41,7 @@ digit = (string "0" >>= \_ -> return 0)
3841
<|> (string "8" >>= \_ -> return 8)
3942
<|> (string "9" >>= \_ -> return 9)
4043

44+
exprTest :: Parser String Number
4145
exprTest = buildExprParser [[Infix (string "/" >>= \_ -> return (/)) AssocRight]
4246
,[Infix (string "*" >>= \_ -> return (*)) AssocRight]
4347
,[Infix (string "-" >>= \_ -> return (-)) AssocRight]

src/Text/Parsing/Parser.purs.hs

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,68 @@
11
module Text.Parsing.Parser where
22

33
import Prelude
4-
import Control.Monad
4+
55
import Data.Either
66
import Data.Maybe
7+
import Data.Monoid
8+
9+
import Control.Monad
10+
import Control.Monad.Identity
11+
12+
import Control.Monad.Trans
13+
import Control.Monad.State.Class
14+
import Control.Monad.State.Trans
15+
import Control.Monad.Error
16+
import Control.Monad.Error.Class
17+
import Control.Monad.Error.Trans
718

819
data ParseError = ParseError
920
{ message :: String
1021
}
1122

12-
parseError :: String -> ParseError
13-
parseError message = ParseError
14-
{ message: message
15-
}
23+
instance errorParseError :: Error ParseError where
24+
noMsg = ParseError { message: "" }
25+
strMsg msg = ParseError { message: msg }
1626

17-
data ParseResult s a = ParseResult
18-
{ leftover :: s
19-
, consumed :: Boolean
20-
, result :: Either ParseError a
21-
}
27+
data Consumed = Consumed Boolean
2228

23-
parseResult :: forall s a. s -> Boolean -> Either ParseError a -> ParseResult s a
24-
parseResult leftover consumed result = ParseResult
25-
{ leftover: leftover
26-
, consumed: consumed
27-
, result: result
28-
}
29+
runConsumed :: Consumed -> Boolean
30+
runConsumed (Consumed c) = c
31+
32+
data ParserT s m a = ParserT (StateT s (StateT Consumed (ErrorT ParseError m)) a)
33+
34+
unParserT :: forall m s a. ParserT s m a -> StateT s (StateT Consumed (ErrorT ParseError m)) a
35+
unParserT (ParserT p) = p
2936

30-
successResult :: forall s a. s -> Boolean -> a -> ParseResult s a
31-
successResult leftover consumed result = parseResult leftover consumed (Right result)
37+
runParserT :: forall m s a. (Monad m) => s -> ParserT s m a -> m (Either ParseError a)
38+
runParserT s = runErrorT <<< flip evalStateT (Consumed false) <<< flip evalStateT s <<< unParserT
3239

33-
failureResult :: forall s a. s -> Boolean -> ParseError -> ParseResult s a
34-
failureResult leftover consumed err = parseResult leftover consumed (Left err)
40+
type Parser s a = ParserT s Identity a
3541

36-
instance functorParseResult :: Prelude.Functor (ParseResult s) where
37-
(<$>) f (ParseResult o) = parseResult o.leftover o.consumed (f <$> o.result)
42+
runParser :: forall s a. s -> Parser s a -> Either ParseError a
43+
runParser s = runIdentity <<< runParserT s
3844

39-
data Parser s a = Parser (s -> ParseResult s a)
45+
instance monadParserT :: (Monad m) => Monad (ParserT s m) where
46+
return a = ParserT (return a)
47+
(>>=) p f = ParserT (unParserT p >>= (unParserT <<< f))
4048

41-
runParser :: forall s a. Parser s a -> s -> ParseResult s a
42-
runParser (Parser p) s = p s
49+
instance alternativeParserT :: (Monad m) => Alternative (ParserT s m) where
50+
empty = ParserT empty
51+
(<|>) p1 p2 = ParserT (unParserT p1 <|> unParserT p2)
4352

44-
instance monadParser :: Prelude.Monad (Parser s) where
45-
return a = Parser $ \s -> successResult s false a
46-
(>>=) p f = Parser $ \s -> case runParser p s of
47-
ParseResult ({ leftover = s', consumed = consumed, result = Left err }) -> failureResult s' consumed err
48-
ParseResult ({ leftover = s', consumed = consumed, result = Right a }) -> runParser (f a) s'
53+
instance monadTransParserT :: MonadTrans (ParserT s) where
54+
lift m = ParserT (lift (lift (lift m)))
4955

50-
instance monadAlternative :: Prelude.Alternative (Parser s) where
51-
empty = fail "No alternative"
52-
(<|>) p1 p2 = Parser $ \s -> case runParser p1 s of
53-
ParseResult ({ leftover = s', consumed = false, result = Left _ }) -> runParser p2 s
54-
res -> res
56+
instance monadErrorParserT :: (Monad m) => MonadError ParseError (ParserT s m) where
57+
throwError e = ParserT (throwError e)
58+
catchError p f = ParserT (catchError (unParserT p) (unParserT <<< f))
5559

56-
fail :: forall s a. String -> Parser s a
57-
fail message = Parser $ \s -> failureResult s false (parseError message)
60+
instance monadStateParserT :: (Monad m) => MonadState s (ParserT s m) where
61+
state f = ParserT (state f)
5862

63+
instance monadStateConsumerParserT :: (Monad m) => MonadState Consumed (ParserT s m) where
64+
state f = ParserT (state f)
5965

66+
fail :: forall m s a. (Monad m) => String -> ParserT s m a
67+
fail message = throwError (ParseError { message: message })
6068

src/Text/Parsing/Parser/Combinators.purs.hs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,114 @@
11
module Text.Parsing.Parser.Combinators where
22

33
import Prelude
4+
45
import Data.Maybe
56
import Data.Array
67
import Data.Either
8+
9+
import Control.Monad
10+
11+
import Control.Monad.Error.Trans
12+
import Control.Monad.Error.Class
13+
import Control.Monad.State.Trans
14+
import Control.Monad.State.Class
15+
716
import Text.Parsing.Parser
817

9-
many :: forall s a. Parser s a -> Parser s [a]
18+
many :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m [a]
1019
many p = many1 p <|> return []
1120

12-
many1 :: forall s a. Parser s a -> Parser s [a]
21+
many1 :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m [a]
1322
many1 p = do a <- p
1423
as <- many p
1524
return (a : as)
1625

17-
(<?>) :: forall s a. Parser s a -> String -> Parser s a
26+
(<?>) :: forall m s a. (Monad m) => ParserT s m a -> String -> ParserT s m a
1827
(<?>) p msg = p <|> fail msg
1928

20-
between :: forall s a open close. Parser s open -> Parser s close -> ({} -> Parser s a) -> Parser s a
29+
between :: forall m s a open close. (Monad m) => ParserT s m open -> ParserT s m close -> ({} -> ParserT s m a) -> ParserT s m a
2130
between open close p = do
2231
open
2332
a <- p {}
2433
close
2534
return a
2635

27-
option :: forall s a. a -> Parser s a -> Parser s a
36+
option :: forall m s a. (Monad m) => a -> ParserT s m a -> ParserT s m a
2837
option a p = p <|> return a
2938

30-
optional :: forall s a. Parser s a -> Parser s {}
39+
optional :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m {}
3140
optional p = (do p
3241
return {}) <|> return {}
3342

34-
optionMaybe :: forall s a. Parser s a -> Parser s (Maybe a)
43+
optionMaybe :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (Maybe a)
3544
optionMaybe p = option Nothing (Just <$> p)
3645

37-
try :: forall s a. Parser s a -> Parser s a
38-
try p = Parser $ \s -> case runParser p s of
39-
ParseResult ({ consumed = true, result = Left err }) -> failureResult s false err
40-
res -> res
46+
try :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m a
47+
try p = catchError p $ \e -> do
48+
Consumed consumed <- get
49+
when consumed $ put (Consumed false)
50+
throwError (e :: ParseError)
4151

42-
sepBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
52+
sepBy :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
4353
sepBy p sep = sepBy1 p sep <|> return []
4454

45-
sepBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
55+
sepBy1 :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
4656
sepBy1 p sep = do
4757
a <- p
4858
as <- many $ do
4959
sep
5060
p
5161
return (a : as)
5262

53-
sepEndBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
63+
sepEndBy :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
5464
sepEndBy p sep = sepEndBy1 p sep <|> return []
5565

56-
sepEndBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
66+
sepEndBy1 :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
5767
sepEndBy1 p sep = do
5868
a <- p
5969
(do sep
6070
as <- sepEndBy p sep
6171
return (a : as)) <|> return [a]
6272

63-
endBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
73+
endBy1 :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
6474
endBy1 p sep = many1 $ do
6575
a <- p
6676
sep
6777
return a
6878

69-
endBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
79+
endBy :: forall m s a sep. (Monad m) => ParserT s m a -> ParserT s m sep -> ParserT s m [a]
7080
endBy p sep = many $ do
7181
a <- p
7282
sep
7383
return a
7484

75-
chainr :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
85+
chainr :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
7686
chainr p f a = chainr1 p f <|> return a
7787

78-
chainl :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
88+
chainl :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
7989
chainl p f a = chainl1 p f <|> return a
8090

81-
chainl1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
91+
chainl1 :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> ParserT s m a
8292
chainl1 p f = do
8393
a <- p
8494
chainl1' p f a
8595

86-
chainl1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
96+
chainl1' :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
8797
chainl1' p f a = (do f' <- f
8898
a' <- p
8999
chainl1' p f (f' a a')) <|> return a
90100

91-
chainr1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
101+
chainr1 :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> ParserT s m a
92102
chainr1 p f = do
93103
a <- p
94104
chainr1' p f a
95105

96-
chainr1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
106+
chainr1' :: forall m s a. (Monad m) => ParserT s m a -> ParserT s m (a -> a -> a) -> a -> ParserT s m a
97107
chainr1' p f a = (do f' <- f
98108
a' <- chainr1 p f
99109
return $ f' a a') <|> return a
100110

101-
choice :: forall s a. [Parser s a] -> Parser s a
111+
choice :: forall m s a. (Monad m) => [ParserT s m a] -> ParserT s m a
102112
choice [] = fail "Nothing to parse"
103113
choice [x] = x
104114
choice (x:xs) = x <|> choice xs

0 commit comments

Comments
 (0)