5 Sep 2013 11:18

## a little parsec enhancement

Hi,

when thinking about this SO question, I couldn't find a combinator that allows a parser to optionally fail without consuming input, or consume input and return its value. So I'm suggesting such a function:

-- | <at> emptyIf p <at> parses <at> p <at> and if its return value is <at> Nothing <at> , pretends -- that an error has occured with no input consumed. -- -- If <at> p <at> fails and consumes some input, so does <at> emptyIf p <at> . Combine with -- 'try' if this is undesirable. emptyIf :: (Stream s m t) => ParsecT s u m (Maybe a) -> ParsecT s u m a emptyIf p = ParsecT \$ \s cok cerr eok eerr -> let cok' (Just x) s e = cok x s e cok' Nothing _ e = eerr e eok' (Just x) s e = eok x s e eok' Nothing _ e = eerr e in unParser p s cok' cerr eok' eerr

With this function, the answer to the SO question becomes really easy:

rcomb :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b rcomb p q = emptyIf \$ runMaybeT (opt p *> opt q) where opt = MaybeT . optional -- optional from Control.Applicative!

Whenever p or q fails without consuming input, then rcomb p q fails without consuming input.

Unfortunately ParsecT constructor isn‘t exported so I’m not able to implement it outside parsec. (Perhaps it would make sense to export ParsecT in some module such as Text.Parsec.Internal?) Therefore I'm suggesting to add such a function to parsec (darcs patch included). Perhaps change the name, I couldn't think of anything better.

Best regards,
Petr

```1 patch for repository http://code.haskell.org/parsec3:

Thu Sep  5 11:12:47 CEST 2013  Petr Pudlak <petr <at> pudlak.name>
* Add 'emptyIf' which allows a parser to optinally fail without consuming any input.

New patches:

[Add 'emptyIf' which allows a parser to optinally fail without consuming any input.
Petr Pudlak <petr <at> pudlak.name>**20130905091247
Ignore-this: 59b93c660fe860acd9a5fff887f7678f
] {
hunk ./Text/Parsec/Prim.hs 38
, parserPlus
, (<?>)
, (<|>)
+    , emptyIf
, label
, labels
hunk ./Text/Parsec/Prim.hs 455
p' = ParsecT \$ \s cok cerr eok eerr ->
unParser p s eok cerr eok eerr

+-- |  <at> emptyIf p <at>  parses  <at> p <at>  and if its return value is  <at> Nothing <at> , pretends
+-- that an error has occured with no input consumed.
+--
+-- If  <at> p <at>  fails and consumes some input, so does  <at> emptyIf p <at> . Combine with
+-- 'try' if this is undesirable.
+
+emptyIf :: (Stream s m t) => ParsecT s u m (Maybe a) -> ParsecT s u m a
+emptyIf p = ParsecT \$ \s cok  cerr eok eerr ->
+                        let cok' (Just x) s e = cok x s e
+                            cok' Nothing  _ e = eerr e
+                            eok' (Just x) s e = eok x s e
+                            eok' Nothing  _ e = eerr e
+                        in unParser p s cok' cerr eok' eerr
+
+
-- | The parser  <at> token showTok posFromTok testTok <at>  accepts a token  <at> t <at>
-- with result  <at> x <at>  when the function  <at> testTok t <at>  returns  <at> 'Just' x <at> . The
-- source position of the  <at> t <at>  should be returned by  <at> posFromTok t <at>  and
}

Context:

Bjorn Buckwalter <bjorn <at> buckwalter.se>**20130821095713
Ignore-this: 304217ec8b73f59edcd96dd13aca67af
]
[TAG 3.1.3
Antoine Latter <aslatter <at> gmail.com>**20120612020909
Ignore-this: 7100375a3e4853c09f1ea993ae32eed7
]
Patch bundle hash:
173111b8bbc5a6eb69d41926053184c35ae9b3cc
```
```_______________________________________________
```
5 Sep 2013 13:38

### Re: a little parsec enhancement

```* Petr Pudlák <petr.mvd <at> gmail.com> [2013-09-05 11:18:25+0200]
> Unfortunately |ParsecT| constructor isn't exported so I'm not able to
> implement it outside /parsec/.

No, but there's an 'mkPT' function which is equivalent to the ParsecT
constructor.

(Although I, too, wish the ParsecT constructor were exposed.)

Roman
```
```_______________________________________________
```
6 Sep 2013 21:21

### Re: a little parsec enhancement

```Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):
> * Petr Pudlák <petr.mvd <at> gmail.com> [2013-09-05 11:18:25+0200]
>> Unfortunately |ParsecT| constructor isn't exported so I'm not able to
>> implement it outside /parsec/.
> No, but there's an 'mkPT' function which is equivalent to the ParsecT
> constructor.
>
> (Although I, too, wish the ParsecT constructor were exposed.)
>
> Roman
Yes, I tried to use `mkPT`, but the result looked very complicated and I
wasn't quite sure if it'll be working correctly in all cases.
Implementing the same thing with the `ParsecT` constructor is simple and
comprehensible.

Best regards,
Petr
```
6 Sep 2013 22:56

### Re: a little parsec enhancement

The exported `mkPT` is equivalent to the old 'ParsecT' data constructor from parsec 3.0.x.

I wouldn't mind exporting a similar alias for the new 'ParsecT' constructor from 3.1.x.

On Fri, Sep 6, 2013 at 2:21 PM, Petr Pudlák wrote:
Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):

* Petr Pudlák <petr.mvd <at> gmail.com> [2013-09-05 11:18:25+0200]
Unfortunately |ParsecT| constructor isn't exported so I'm not able to
implement it outside /parsec/.
No, but there's an 'mkPT' function which is equivalent to the ParsecT
constructor.

(Although I, too, wish the ParsecT constructor were exposed.)

Roman
Yes, I tried to use `mkPT`, but the result looked very complicated and I wasn't quite sure if it'll be working correctly in all cases. Implementing the same thing with the `ParsecT` constructor is simple and comprehensible.

Best regards,
Petr

```_______________________________________________
```
9 Sep 2013 11:14

### Re: a little parsec enhancement

I'd appreciate exporting adding such aliases for creating and running ParsecT the 3.1.x way.

Thanks,
Petr

Dne 09/06/2013 10:56 PM, Antoine Latter napsal(a):
The exported `mkPT` is equivalent to the old 'ParsecT' data constructor from parsec 3.0.x.

I wouldn't mind exporting a similar alias for the new 'ParsecT' constructor from 3.1.x.

On Fri, Sep 6, 2013 at 2:21 PM, Petr Pudlák wrote:
Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):

* Petr Pudlák <petr.mvd <at> gmail.com> [2013-09-05 11:18:25+0200]
Unfortunately |ParsecT| constructor isn't exported so I'm not able to
implement it outside /parsec/.
No, but there's an 'mkPT' function which is equivalent to the ParsecT
constructor.

(Although I, too, wish the ParsecT constructor were exposed.)

Roman
Yes, I tried to use `mkPT`, but the result looked very complicated and I wasn't quite sure if it'll be working correctly in all cases. Implementing the same thing with the `ParsecT` constructor is simple and comprehensible.

Best regards,
Petr

```_______________________________________________