a little parsec enhancement

Hi, when thinking about this SO question http://stackoverflow.com/q/18583416/1333025, 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: |-- | @emptyIf p@ parses @p@ and if its return value is @Nothing@, pretends -- that an error has occured with no input consumed. -- -- If @p@ fails and consumes some input, so does @emptyIf p@. 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

* Petr Pudlák
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

Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):
* Petr Pudlák
[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

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
Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):
* Petr Pudlák
[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

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
mailto:petr.mvd@gmail.com> wrote: Dne 09/05/2013 01:38 PM, Roman Cheplyaka napsal(a):
* Petr Pudlák
mailto:petr.mvd@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
participants (3)
-
Antoine Latter
-
Petr Pudlák
-
Roman Cheplyaka