Very, very interesting. Thank you, Yitzchak. I&#39;ll try.<br><br><div class="gmail_quote">2011/9/15 Yitzchak Gale <span dir="ltr">&lt;<a href="mailto:gale@sefer.org">gale@sefer.org</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">Alexander.Vladislav.Popov wrote:<br>
&gt;&gt; Help me to parse multiline comments (like /* ... */ or even like /*- ...<br>
&gt;&gt; -*/) using attoparsec.<br>
<br>
</div><div class="im">Daniel Fischer wrote:<br>
&gt; The docs for manyTill at<br>
&gt; <a href="http://hackage.haskell.org/packages/archive/attoparsec/0.9.1.2/doc/html/Data-" target="_blank">http://hackage.haskell.org/packages/archive/attoparsec/0.9.1.2/doc/html/Data-</a><br>
&gt; Attoparsec-Combinator.html<br>
&gt; have the example<br>
&gt;<br>
&gt; simpleComment   = string &quot;&lt;!--&quot; *&gt; manyTill anyChar (try (string &quot;--&gt;&quot;))<br>
<br>
</div>Unfortunately, many of the examples in the documentation for Attoparsec<br>
are just lifted directly from the Parsec documentation, so they<br>
need to be modified somewhat to work in Attoparsed.<br>
This is one of those cases.<br>
<br>
First of all, the string function in Attoparsec has type<br>
<br>
string :: ByteString -&gt; Parser ByteString<br>
<br>
So you can&#39;t use a String as its argument directly; you need to<br>
wrap the String with Data.ByteString.Char8.pack.<br>
<br>
If you are parsing source code text, you anyway would be better<br>
off using Text instead of String and attoparsec-text instead of<br>
attoparsec. That, together with the OverloadedStrings extension,<br>
will solve that problem and more. Then you don&#39;t even need<br>
the &quot;string&quot; function. Just use string literals to parse strings,<br>
and the compiler will automatically insert calls to &quot;string&quot;.<br>
<br>
The next issue is that you don&#39;t need &quot;try&quot; - unlike in Parsec,<br>
the string combinator in Attoparsec does *not* consume any<br>
input when it fails.<br>
<br>
Finally, if you are bothering to use attoparsec, it is presumably<br>
because you want the super speed it is able to achieve using<br>
fusion. But the documentation points out that you don&#39;t get that<br>
fusion for combinators like manyTill, only for &quot;byte-oriented&quot;<br>
combinators like takeTill. So you should factor the parser to<br>
parse the comment (quickly!) into chunks beginning with<br>
&#39;*&#39;, then use manyTill only on the chunks.<br>
<br>
Here is an untested example with the above modifications:<br>
<br>
comment = &quot;/*&quot; .*&gt; (emptyComment &lt;|&gt; T.concat &lt;$&gt; commentChunks)<br>
emptyComment = &quot;*/&quot; .*&gt; pure T.empty<br>
commentChunks = manyTill (takeWhile1 (/= &#39;*&#39;)) (string &quot;*/&quot;)<br>
<br>
I did need to use the string keyword with manyTill, because<br>
manyTill is too polymorphic for the compiler to be able to<br>
deduce the type of the string literal. Since manyTill is so<br>
common, I often define a type-specialized version of it<br>
for convenience:<br>
<br>
manyTillS :: Parser a -&gt; Parser Text -&gt; Parser [a]<br>
manyTillS = manyTill<br>
<br>
That is analogous to &quot;.*&gt;&quot;, attoparsec-text&#39;s type-specialized<br>
version of  &quot;*&gt;&quot; from Control.Applicative.<br>
<br>
Then you can write:<br>
<br>
commentChunks = takeWhile1 (/= &#39;*&#39;) `manyTillS` &quot;*/&quot;<br>
<br>
Regards,<br>
Yitz<br>
</blockquote></div><br>