Skip to content

Commit da1ef24

Browse files
committed
Update for 1.0 core libraries
1 parent 98c0e23 commit da1ef24

File tree

6 files changed

+152
-145
lines changed

6 files changed

+152
-145
lines changed

bower.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@
2121
"url": "git://github.com/paf31/purescript-string-parsers.git"
2222
},
2323
"dependencies": {
24-
"purescript-control": "~0.3.1",
25-
"purescript-arrays": "~0.4.2",
26-
"purescript-maybe": "~0.3.4",
27-
"purescript-strings": "~0.7.0",
28-
"purescript-foldable-traversable": "~0.4.0",
29-
"purescript-either": "~0.2.3",
30-
"purescript-lists": "~0.7.8"
24+
"purescript-control": "^1.0.0",
25+
"purescript-arrays": "^1.0.0",
26+
"purescript-maybe": "^1.0.0",
27+
"purescript-strings": "^1.0.0",
28+
"purescript-foldable-traversable": "^1.0.0",
29+
"purescript-either": "^1.0.0",
30+
"purescript-lists": "^1.0.0"
3131
},
3232
"devDependencies": {
33-
"purescript-math": "~0.2.0",
34-
"purescript-quickcheck": "~0.12.0"
33+
"purescript-math": "^2.0.0",
34+
"purescript-quickcheck": "^1.0.0"
3535
}
3636
}

src/Text/Parsing/StringParser.purs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
module Text.Parsing.StringParser where
44

55
import Prelude
6-
6+
import Control.MonadPlus (class MonadPlus, class MonadZero, class Alternative)
7+
import Control.Monad.Rec.Class (class MonadRec, tailRecM)
8+
import Control.Plus (class Plus, class Alt)
9+
import Data.Bifunctor (bimap, lmap)
710
import Data.Either (Either(..))
811

9-
import Control.Alt
10-
import Control.Alternative
11-
import Control.MonadPlus
12-
import Control.Plus
13-
1412
-- | A poition in an input string.
1513
type Pos = Int
1614

1715
-- | Strings are represented as a string with an index from the
1816
-- | start of the string.
19-
-- |
17+
-- |
2018
-- | `{ str: s, pos: n }` is interpreted as the substring of `s`
2119
-- | starting at index n.
22-
-- |
20+
-- |
2321
-- | This allows us to avoid repeatedly finding substrings
2422
-- | every time we match a character.
2523
type PosString = { str :: String, pos :: Pos }
@@ -35,56 +33,63 @@ instance eqParseError :: Eq ParseError where
3533

3634
-- | A parser is represented as a function which takes a pair of
3735
-- | continuations for failure and success.
38-
data Parser a = Parser (forall r. PosString -> (Pos -> ParseError -> r) -> (a -> PosString -> r) -> r)
36+
data Parser a = Parser (PosString -> Either { pos :: Pos, error :: ParseError } { result :: a, suffix :: PosString })
3937

4038
-- | Run a parser by providing success and failure continuations.
41-
unParser :: forall a r. Parser a -> PosString -> (Pos -> ParseError -> r) -> (a -> PosString -> r) -> r
39+
unParser :: forall a. Parser a -> PosString -> Either { pos :: Pos, error :: ParseError } { result :: a, suffix :: PosString }
4240
unParser (Parser p) = p
4341

4442
-- | Run a parser for an input string, returning either an error or a result.
4543
runParser :: forall a. Parser a -> String -> Either ParseError a
46-
runParser p s = unParser p { str: s, pos: 0 } (\_ err -> Left err) (\a _ -> Right a)
44+
runParser (Parser p) s = bimap _.error _.result (p { str: s, pos: 0 })
4745

4846
instance functorParser :: Functor Parser where
49-
map f p = Parser (\s fc sc ->
50-
unParser p s fc (\a s' -> sc (f a) s'))
47+
map f (Parser p) = Parser (map (\{ result, suffix } -> { result: f result, suffix }) <<< p)
5148

5249
instance applyParser :: Apply Parser where
53-
apply f x = Parser (\s fc sc ->
54-
unParser f s fc (\f' s' ->
55-
unParser x s' fc (\x' s'' -> sc (f' x') s'')))
50+
apply (Parser p1) (Parser p2) = Parser \s -> do
51+
{ result: f, suffix: s1 } <- p1 s
52+
{ result: x, suffix: s2 } <- p2 s1
53+
pure { result: f x, suffix: s2 }
5654

5755
instance applicativeParser :: Applicative Parser where
58-
pure a = Parser (\s _ sc -> sc a s)
56+
pure a = Parser \s -> Right { result: a, suffix: s }
5957

6058
instance altParser :: Alt Parser where
61-
alt 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)
59+
alt (Parser p1) (Parser p2) = Parser \s ->
60+
case p1 s of
61+
Left { error, pos } | s.pos == pos -> p2 s
62+
| otherwise -> Left { error, pos }
63+
right -> right
6764

6865
instance plusParser :: Plus Parser where
6966
empty = fail "No alternative"
7067

7168
instance alternativeParser :: Alternative Parser
7269

7370
instance bindParser :: Bind Parser where
74-
bind p f = Parser (\s fc sc ->
75-
unParser p s fc (\a s' ->
76-
unParser (f a) s' fc sc))
71+
bind (Parser p) f = Parser \s -> do
72+
{ result, suffix } <- p s
73+
unParser (f result) suffix
7774

7875
instance monadParser :: Monad Parser
7976

77+
instance monadZeroParser :: MonadZero Parser
78+
8079
instance monadPlusParser :: MonadPlus Parser
8180

81+
instance monadRecParser :: MonadRec Parser where
82+
tailRecM f a = Parser \str -> tailRecM (\st -> map split (unParser (f st.state) st.str)) { state: a, str }
83+
where
84+
split { result: Left state, suffix: str } = Left { state, str }
85+
split { result: Right b, suffix } = Right { result: b, suffix }
86+
8287
-- | Fail with the specified message.
8388
fail :: forall a. String -> Parser a
84-
fail msg = Parser (\{ pos = pos } fc _ -> fc pos (ParseError msg))
89+
fail msg = Parser \{ pos } -> Left { pos, error: ParseError msg }
8590

8691
-- | In case of error, the default behavior is to backtrack if no input was consumed.
8792
-- |
8893
-- | `try p` backtracks even if input was consumed.
8994
try :: forall a. Parser a -> Parser a
90-
try p = Parser (\(s@{ pos = pos }) fc sc -> unParser p s (\_ -> fc pos) sc)
95+
try (Parser p) = Parser \(s@{ pos }) -> lmap (_ { pos = pos}) (p s)

src/Text/Parsing/StringParser/Combinators.purs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,67 @@ module Text.Parsing.StringParser.Combinators where
44

55
import Prelude
66

7+
import Data.Either (Either(..))
78
import Data.Maybe (Maybe(..))
89
import Data.List (List(..), singleton)
9-
import Data.Foldable (Foldable, foldl)
10+
import Data.Foldable (class Foldable, foldl)
1011

1112
import Control.Alt ((<|>))
1213
import Control.Apply ((*>))
1314

14-
import Text.Parsing.StringParser
15+
import Text.Parsing.StringParser (Parser(..), fail, unParser)
1516

1617
-- | Read ahead without consuming input.
1718
lookAhead :: forall a. Parser a -> Parser a
18-
lookAhead p = Parser \ps fc sc -> unParser p ps fc (\s _ -> sc s ps)
19+
lookAhead (Parser p) = Parser \s ->
20+
case p s of
21+
Right { result } -> Right { result, suffix: s }
22+
left -> left
1923

2024
-- | Match zero or more times.
2125
many :: forall a. Parser a -> Parser (List a)
22-
many p = many1 p <|> return Nil
26+
many p = many1 p <|> pure Nil
2327

2428
-- | Match one or more times.
2529
many1 :: forall a. Parser a -> Parser (List a)
2630
many1 p = do
2731
a <- p
2832
as <- many p
29-
return (Cons a as)
33+
pure (Cons a as)
3034

3135
-- | Provide an error message in case of failure.
32-
(<?>) :: forall a. Parser a -> String -> Parser a
33-
(<?>) p msg = p <|> fail msg
36+
withError :: forall a. Parser a -> String -> Parser a
37+
withError p msg = p <|> fail msg
38+
39+
infixl 3 withError as <?>
3440

3541
-- | Take the fixed point of a parser function. This function is sometimes useful when building recursive parsers.
3642
fix :: forall a. (Parser a -> Parser a) -> Parser a
37-
fix f = Parser (\s fc sc -> unParser (f (fix f)) s fc sc)
43+
fix f = Parser \s -> unParser (f (fix f)) s
3844

3945
-- | Parse a string between opening and closing markers.
4046
between :: forall a open close. Parser open -> Parser close -> Parser a -> Parser a
4147
between open close p = do
4248
open
4349
a <- p
4450
close
45-
return a
51+
pure a
4652

4753
-- | Parse a value with a default value in case of failure.
4854
option :: forall a. a -> Parser a -> Parser a
49-
option a p = p <|> return a
55+
option a p = p <|> pure a
5056

5157
-- | Attempt to parse a value.
5258
optional :: forall a. Parser a -> Parser Unit
53-
optional p = (p >>= \_ -> return unit) <|> return unit
59+
optional p = (p >>= \_ -> pure unit) <|> pure unit
5460

55-
-- | Attempt to parse a value, returning `Nothing` in case of failure.
61+
-- | Attempt to parse a value, pureing `Nothing` in case of failure.
5662
optionMaybe :: forall a. Parser a -> Parser (Maybe a)
5763
optionMaybe p = option Nothing (Just <$> p)
5864

5965
-- | Parse zero or more separated values.
6066
sepBy :: forall a sep. Parser a -> Parser sep -> Parser (List a)
61-
sepBy p sep = sepBy1 p sep <|> return Nil
67+
sepBy p sep = sepBy1 p sep <|> pure Nil
6268

6369
-- | Parse one or more separated values.
6470
sepBy1 :: forall a sep. Parser a -> Parser sep -> Parser (List a)
@@ -67,41 +73,41 @@ sepBy1 p sep = do
6773
as <- many $ do
6874
sep
6975
p
70-
return (Cons a as)
76+
pure (Cons a as)
7177

7278
-- | Parse zero or more separated values, optionally ending with a separator.
7379
sepEndBy :: forall a sep. Parser a -> Parser sep -> Parser (List a)
74-
sepEndBy p sep = sepEndBy1 p sep <|> return Nil
80+
sepEndBy p sep = sepEndBy1 p sep <|> pure Nil
7581

7682
-- | Parse one or more separated values, optionally ending with a separator.
7783
sepEndBy1 :: forall a sep. Parser a -> Parser sep -> Parser (List a)
7884
sepEndBy1 p sep = do
7985
a <- p
8086
(do sep
8187
as <- sepEndBy p sep
82-
return (Cons a as)) <|> return (singleton a)
88+
pure (Cons a as)) <|> pure (singleton a)
8389

8490
-- | Parse zero or more separated values, ending with a separator.
8591
endBy1 :: forall a sep. Parser a -> Parser sep -> Parser (List a)
8692
endBy1 p sep = many1 $ do
8793
a <- p
8894
sep
89-
return a
95+
pure a
9096

9197
-- | Parse one or more separated values, ending with a separator.
9298
endBy :: forall a sep. Parser a -> Parser sep -> Parser (List a)
9399
endBy p sep = many $ do
94100
a <- p
95101
sep
96-
return a
102+
pure a
97103

98104
-- | Parse zero or more values separated by a right-associative operator.
99105
chainr :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
100-
chainr p f a = chainr1 p f <|> return a
106+
chainr p f a = chainr1 p f <|> pure a
101107

102108
-- | Parse zero or more values separated by a left-associative operator.
103109
chainl :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
104-
chainl p f a = chainl1 p f <|> return a
110+
chainl p f a = chainl1 p f <|> pure a
105111

106112
-- | Parse one or more values separated by a left-associative operator.
107113
chainl1 :: forall a. Parser a -> Parser (a -> a -> a) -> Parser a
@@ -113,7 +119,7 @@ chainl1 p f = do
113119
chainl1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
114120
chainl1' p f a = (do f' <- f
115121
a' <- p
116-
chainl1' p f (f' a a')) <|> return a
122+
chainl1' p f (f' a a')) <|> pure a
117123

118124
-- | Parse one or more values separated by a right-associative operator.
119125
chainr1 :: forall a. Parser a -> Parser (a -> a -> a) -> Parser a
@@ -125,7 +131,7 @@ chainr1 p f = do
125131
chainr1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
126132
chainr1' p f a = (do f' <- f
127133
a' <- chainr1 p f
128-
return $ f' a a') <|> return a
134+
pure $ f' a a') <|> pure a
129135

130136
-- | Parse using any of a collection of parsers.
131137
choice :: forall f a. (Foldable f) => f (Parser a) -> Parser a
@@ -135,6 +141,6 @@ choice = foldl (<|>) (fail "Nothing to parse")
135141
manyTill :: forall a end. Parser a -> Parser end -> Parser (List a)
136142
manyTill p end = scan
137143
where
138-
scan = (end *> return Nil) <|> do x <- p
139-
xs <- scan
140-
return (Cons x xs)
144+
scan = (end *> pure Nil) <|> do x <- p
145+
xs <- scan
146+
pure (Cons x xs)

src/Text/Parsing/StringParser/Expr.purs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ module Text.Parsing.StringParser.Expr
99

1010
import Prelude
1111

12-
import Data.Foldable
12+
import Control.Alt ((<|>))
13+
import Data.Foldable (foldl, foldr)
1314
import Data.List (List(..))
14-
15-
import Control.Alt
16-
17-
import Text.Parsing.StringParser
18-
import Text.Parsing.StringParser.Combinators
15+
import Text.Parsing.StringParser (Parser)
16+
import Text.Parsing.StringParser.Combinators (choice, (<?>))
1917

2018
-- | Operator associativity types.
2119
data Assoc = AssocNone | AssocLeft | AssocRight
@@ -48,14 +46,14 @@ buildExprParser operators simpleExpr =
4846
prefixOp = choice accum.prefix <?> ""
4947
postfixOp = choice accum.postfix <?> ""
5048

51-
postfixP = postfixOp <|> return id
52-
prefixP = prefixOp <|> return id
49+
postfixP = postfixOp <|> pure id
50+
prefixP = prefixOp <|> pure id
5351
in do
5452
x <- termP prefixP term postfixP
5553
rassocP x rassocOp prefixP term postfixP
5654
<|> lassocP x lassocOp prefixP term postfixP
5755
<|> nassocP x nassocOp prefixP term postfixP
58-
<|> return x
56+
<|> pure x
5957
<?> "operator"
6058

6159
splitOp :: forall b. Operator b -> SplitAccum b -> SplitAccum b
@@ -71,10 +69,10 @@ buildExprParser operators simpleExpr =
7169
y <- do
7270
z <- termP prefixP term postfixP
7371
rassocP1 z rassocOp prefixP term postfixP
74-
return (f x y)
72+
pure (f x y)
7573

7674
rassocP1 :: forall b c d. b -> Parser (b -> b -> b) -> Parser (c -> d) -> Parser c -> Parser (d -> b) -> Parser b
77-
rassocP1 x rassocOp prefixP term postfixP = rassocP x rassocOp prefixP term postfixP <|> return x
75+
rassocP1 x rassocOp prefixP term postfixP = rassocP x rassocOp prefixP term postfixP <|> pure x
7876

7977
lassocP :: forall b c d. b -> Parser (b -> b -> b) -> Parser (c -> d) -> Parser c -> Parser (d -> b) -> Parser b
8078
lassocP x lassocOp prefixP term postfixP = do
@@ -83,19 +81,19 @@ buildExprParser operators simpleExpr =
8381
lassocP1 (f x y) lassocOp prefixP term postfixP
8482

8583
lassocP1 :: forall b c d. b -> Parser (b -> b -> b) -> Parser (c -> d) -> Parser c -> Parser (d -> b) -> Parser b
86-
lassocP1 x lassocOp prefixP term postfixP = lassocP x lassocOp prefixP term postfixP <|> return x
84+
lassocP1 x lassocOp prefixP term postfixP = lassocP x lassocOp prefixP term postfixP <|> pure x
8785

8886
nassocP :: forall b c d. b -> Parser (b -> b -> b) -> Parser (c -> d) -> Parser c -> Parser (d -> b) -> Parser b
8987
nassocP x nassocOp prefixP term postfixP = do
9088
f <- nassocOp
9189
y <- termP prefixP term postfixP
92-
return (f x y)
90+
pure (f x y)
9391

9492
termP :: forall b c d. Parser (b -> c) -> Parser b -> Parser (c -> d) -> Parser d
9593
termP prefixP term postfixP = do
9694
pre <- prefixP
9795
x <- term
9896
post <- postfixP
99-
return (post (pre x))
97+
pure (post (pre x))
10098

10199
in foldl (makeParser) simpleExpr operators

0 commit comments

Comments
 (0)