Skip to content

Commit 579ddbe

Browse files
committed
Merge pull request #1 from purescript-contrib/alternative
Add Alt, Plus, MonadPlus, update Alternative
2 parents de0cf6b + 4e2349c commit 579ddbe

File tree

6 files changed

+77
-59
lines changed

6 files changed

+77
-59
lines changed

bower.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
"package.json"
1616
],
1717
"dependencies": {
18-
"purescript-arrays" : "*",
19-
"purescript-maybe" : "*",
20-
"purescript-strings" : "*",
18+
"purescript-control": "~0.2.0",
19+
"purescript-arrays": "~0.2.0",
20+
"purescript-maybe": "~0.2.0",
21+
"purescript-strings": "*",
2122
"purescript-foldable-traversable" : "*"
2223
},
2324
"devDependencies": {
24-
"purescript-math" : "*",
25-
"purescript-quickcheck" : "*"
25+
"purescript-math": "*",
26+
"purescript-quickcheck": "*"
2627
}
2728
}

src/Text/Parsing/StringParser.purs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
module Text.Parsing.StringParser where
2-
2+
33
import Data.Either (Either(..))
44

5+
import Control.Alt
6+
import Control.Alternative
7+
import Control.MonadPlus
8+
import Control.Plus
9+
510
type Pos = Number
611

7-
--
12+
--
813
-- Strings are represented as a string with an index from the
9-
-- start of the string.
14+
-- start of the string.
1015
--
1116
-- { str: s, pos: n } is interpreted as the substring of s
1217
-- starting at index n.
@@ -25,7 +30,7 @@ instance showParseError :: Show ParseError where
2530
show (ParseError msg) = msg
2631

2732
--
28-
-- A parser is represented as a function which takes a pair of
33+
-- A parser is represented as a function which takes a pair of
2934
-- continuations for failure and success.
3035
--
3136
data Parser a = Parser (forall r. PosString -> (Pos -> ParseError -> r) -> (a -> PosString -> r) -> r)
@@ -41,35 +46,41 @@ runParser p s = unParser p { str: s, pos: 0 } (\_ err -> Left err) (\a _ -> Righ
4146
--
4247

4348
instance functorParser :: Functor Parser where
44-
(<$>) f p = Parser (\s fc sc ->
49+
(<$>) f p = Parser (\s fc sc ->
4550
unParser p s fc (\a s' -> sc (f a) s'))
4651

4752
instance applyParser :: Apply Parser where
48-
(<*>) f x = Parser (\s fc sc ->
53+
(<*>) f x = Parser (\s fc sc ->
4954
unParser f s fc (\f' s' ->
5055
unParser x s' fc (\x' s'' -> sc (f' x') s'')))
5156

5257
instance applicativeParser :: Applicative Parser where
5358
pure a = Parser (\s _ sc -> sc a s)
5459

60+
instance altParser :: Alt Parser where
61+
(<|>) p1 p2 = Parser (\s fc sc ->
62+
unParser p1 s (\pos msg ->
63+
if s.pos == pos
64+
then unParser p2 s fc sc
65+
else fc pos msg)
66+
sc)
67+
68+
instance plusParser :: Plus Parser where
69+
empty = fail "No alternative"
70+
71+
instance alternativeParser :: Alternative Parser
72+
5573
instance bindParser :: Bind Parser where
5674
(>>=) p f = Parser (\s fc sc ->
5775
unParser p s fc (\a s' ->
5876
unParser (f a) s' fc sc))
5977

6078
instance monadParser :: Monad Parser
6179

62-
instance alternativeParser :: Alternative Parser where
63-
empty = fail "No alternative"
64-
(<|>) p1 p2 = Parser (\s fc sc ->
65-
unParser p1 s (\pos msg ->
66-
if s.pos == pos
67-
then unParser p2 s fc sc
68-
else fc pos msg)
69-
sc)
80+
instance monadPlusParser :: MonadPlus Parser
7081

7182
fail :: forall a. String -> Parser a
7283
fail msg = Parser (\{ pos = pos } fc _ -> fc pos (ParseError msg))
7384

7485
try :: forall a. Parser a -> Parser a
75-
try p = Parser (\(s@{ pos = pos }) fc sc -> unParser p s (\_ -> fc pos) sc)
86+
try p = Parser (\(s@{ pos = pos }) fc sc -> unParser p s (\_ -> fc pos) sc)

src/Text/Parsing/StringParser/Combinators.purs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
module Text.Parsing.StringParser.Combinators where
22

33
import Data.Maybe (Maybe(..))
4+
5+
import Control.Alt
6+
47
import Text.Parsing.StringParser
58

69
many :: forall a. Parser a -> Parser [a]
@@ -22,14 +25,14 @@ between :: forall a open close. Parser open -> Parser close -> Parser a -> Parse
2225
between open close p = do
2326
open
2427
a <- p
25-
close
28+
close
2629
return a
2730

2831
option :: forall a. a -> Parser a -> Parser a
2932
option a p = p <|> return a
3033

31-
optional :: forall a. Parser a -> Parser {}
32-
optional p = (p >>= \_ -> return {}) <|> return {}
34+
optional :: forall a. Parser a -> Parser Unit
35+
optional p = (p >>= \_ -> return unit) <|> return unit
3336

3437
optionMaybe :: forall a. Parser a -> Parser (Maybe a)
3538
optionMaybe p = option Nothing (Just <$> p)
@@ -56,7 +59,7 @@ sepEndBy1 p sep = do
5659
return (a : as)) <|> return [a]
5760

5861
endBy1 :: forall a sep. Parser a -> Parser sep -> Parser [a]
59-
endBy1 p sep = many1 $ do
62+
endBy1 p sep = many1 $ do
6063
a <- p
6164
sep
6265
return a

src/Text/Parsing/StringParser/Expr.purs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module Text.Parsing.StringParser.Expr where
33
import Data.Either
44
import Data.Foldable
55

6+
import Control.Alt
7+
68
import Text.Parsing.StringParser
79
import Text.Parsing.StringParser.Combinators
810

@@ -22,27 +24,27 @@ type SplitAccum a = { rassoc :: [Parser (a -> a -> a)]
2224

2325
buildExprParser :: forall a. OperatorTable a -> Parser a -> Parser a
2426
buildExprParser operators simpleExpr =
25-
let
27+
let
2628
makeParser term ops =
27-
let
28-
accum = foldr splitOp { rassoc: [], lassoc: [], nassoc: [], prefix: [], postfix: [] } ops
29-
30-
rassocOp = choice accum.rassoc
31-
lassocOp = choice accum.lassoc
32-
nassocOp = choice accum.nassoc
33-
prefixOp = choice accum.prefix <?> ""
34-
postfixOp = choice accum.postfix <?> ""
35-
29+
let
30+
accum = foldr splitOp { rassoc: [], lassoc: [], nassoc: [], prefix: [], postfix: [] } ops
31+
32+
rassocOp = choice accum.rassoc
33+
lassocOp = choice accum.lassoc
34+
nassocOp = choice accum.nassoc
35+
prefixOp = choice accum.prefix <?> ""
36+
postfixOp = choice accum.postfix <?> ""
37+
3638
postfixP = postfixOp <|> return id
37-
prefixP = prefixOp <|> return id
39+
prefixP = prefixOp <|> return id
3840
in do
3941
x <- termP prefixP term postfixP
4042
rassocP x rassocOp prefixP term postfixP
4143
<|> lassocP x lassocOp prefixP term postfixP
4244
<|> nassocP x nassocOp prefixP term postfixP
4345
<|> return x
4446
<?> "operator"
45-
47+
4648
splitOp :: forall a. Operator a -> SplitAccum a -> SplitAccum a
4749
splitOp (Infix op AssocNone) accum = accum { nassoc = op: accum.nassoc }
4850
splitOp (Infix op AssocLeft) accum = accum { lassoc = op: accum.lassoc }
@@ -83,4 +85,4 @@ buildExprParser operators simpleExpr =
8385
post <- postfixP
8486
return (post (pre x))
8587

86-
in foldl (makeParser) simpleExpr operators
88+
in foldl (makeParser) simpleExpr operators
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
module Text.Parsing.StringParser.String where
2-
2+
33
import Data.String (charAt, length, take, indexOf')
44
import Text.Parsing.StringParser
55

6-
eof :: Parser {}
6+
eof :: Parser Unit
77
eof = Parser (\s fc sc -> case s of
8-
{ str = str, pos = i } | i < length str -> fc i (ParseError "Expected EOF")
9-
_ -> sc {} s)
8+
{ str = str, pos = i } | i < length str -> fc i (ParseError "Expected EOF")
9+
_ -> sc unit s)
1010

1111
anyChar :: Parser String
1212
anyChar = Parser (\s fc sc -> case s of
@@ -16,4 +16,4 @@ anyChar = Parser (\s fc sc -> case s of
1616
string :: String -> Parser String
1717
string nt = Parser (\s fc sc -> case s of
1818
{ str = str, pos = i } | indexOf' nt i str == i -> sc nt { str: str, pos: i + length nt }
19-
{ pos = i } -> fc i (ParseError $ "Expected '" ++ nt ++ "'."))
19+
{ pos = i } -> fc i (ParseError $ "Expected '" ++ nt ++ "'."))

tests/Tests.purs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import Data.Either
66

77
import Debug.Trace
88

9+
import Control.Alt
910
import Control.Monad.Eff
1011

11-
import Text.Parsing.StringParser
12+
import Text.Parsing.StringParser
1213
import Text.Parsing.StringParser.Combinators
1314
import Text.Parsing.StringParser.String
1415
import Text.Parsing.StringParser.Expr
@@ -19,38 +20,38 @@ parens :: forall a. Parser a -> Parser a
1920
parens = between (string "(") (string ")")
2021

2122
nested :: Parser Number
22-
nested = fix $ \p -> (do
23+
nested = fix $ \p -> (do
2324
string "a"
2425
return 0) <|> ((+) 1) <$> parens p
2526

26-
parseTest :: forall a eff. (Show a) => Parser a -> String -> Eff (trace :: Trace | eff) {}
27+
parseTest :: forall a eff. (Show a) => Parser a -> String -> Eff (trace :: Trace | eff) Unit
2728
parseTest p input = case runParser p input of
2829
Left (ParseError err) -> print err
2930
Right result -> print result
3031

3132
opTest :: Parser String
32-
opTest = chainl anyChar (do
33+
opTest = chainl anyChar (do
3334
string "+"
3435
return (++)) ""
35-
36+
3637
digit :: Parser Number
37-
digit = (string "0" >>= \_ -> return 0)
38-
<|> (string "1" >>= \_ -> return 1)
39-
<|> (string "2" >>= \_ -> return 2)
40-
<|> (string "3" >>= \_ -> return 3)
41-
<|> (string "4" >>= \_ -> return 4)
42-
<|> (string "5" >>= \_ -> return 5)
43-
<|> (string "6" >>= \_ -> return 6)
44-
<|> (string "7" >>= \_ -> return 7)
45-
<|> (string "8" >>= \_ -> return 8)
46-
<|> (string "9" >>= \_ -> return 9)
38+
digit = (string "0" >>= \_ -> return 0)
39+
<|> (string "1" >>= \_ -> return 1)
40+
<|> (string "2" >>= \_ -> return 2)
41+
<|> (string "3" >>= \_ -> return 3)
42+
<|> (string "4" >>= \_ -> return 4)
43+
<|> (string "5" >>= \_ -> return 5)
44+
<|> (string "6" >>= \_ -> return 6)
45+
<|> (string "7" >>= \_ -> return 7)
46+
<|> (string "8" >>= \_ -> return 8)
47+
<|> (string "9" >>= \_ -> return 9)
4748

4849
exprTest :: Parser Number
4950
exprTest = buildExprParser [[Infix (string "/" >>= \_ -> return (/)) AssocRight]
5051
,[Infix (string "*" >>= \_ -> return (*)) AssocRight]
5152
,[Infix (string "-" >>= \_ -> return (-)) AssocRight]
5253
,[Infix (string "+" >>= \_ -> return (+)) AssocRight]] digit
53-
54+
5455
tryTest :: Parser String
5556
tryTest = try ((++) <$> string "aa" <*> string "bb") <|>
5657
(++) <$> string "aa" <*> string "cc"
@@ -65,7 +66,7 @@ main = do
6566
parseTest (do
6667
as <- string "a" `endBy1` string ","
6768
eof
68-
return as) "a,a,a,"
69+
return as) "a,a,a,"
6970
parseTest opTest "a+b+c"
7071
parseTest exprTest "1*2+3/4-5"
7172
parseTest tryTest "aacc"

0 commit comments

Comments
 (0)