Petr Pudlák | 5 Sep 11:18 2013
Picon

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
     , lookAhead
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:

[Fix haddock module links.
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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Roman Cheplyaka | 5 Sep 13:38 2013

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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Petr Pudlák | 6 Sep 21:21 2013
Picon

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
Antoine Latter | 6 Sep 22:56 2013
Picon

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 <petr.mvd <at> gmail.com> 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

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Petr Pudlák | 9 Sep 11:14 2013
Picon

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 <petr.mvd <at> gmail.com> 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


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Gmane