Cool, I like how this parser can model the &quot;Look, an Eagle&quot; scenario.  For reference:<br><a href="http://www.youtube.com/watch?v=pjh3e198pUQ">http://www.youtube.com/watch?v=pjh3e198pUQ</a><br><br>The parser can &quot;change focus&quot; (that is, change traversal strategy) in response to a successful parse.  In the &quot;Look, an Eagle&quot; scenario, the bear is able to interpret and respond to its input serially and interactively, but when the bear&#39;s input stream is replaced by a new one, the man is able to capture the prize.<br>

<br>-Greg<br><br><br><div class="gmail_quote">On Thu, Oct 1, 2009 at 1:02 PM, Anatoly Yakovenko <span dir="ltr">&lt;<a href="mailto:aeyakovenko@gmail.com">aeyakovenko@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

so whats pretty cool is that I can traverse arbitrary data structures as  well:<br>
<br>
data Tree a = Tree (Tree a) a (Tree a) | Bottom<br>
            deriving Show<br>
<br>
left a = do<br>
   make $ \ st -&gt; do<br>
      case(st) of<br>
         (Bottom) -&gt; eos<br>
         (Tree left val right) -&gt;<br>
            case (a &lt; val) of<br>
               True -&gt; return $ (val, left)<br>
               False -&gt; noMatch<br>
<br>
right a = do<br>
   make $ \ st -&gt; do<br>
      case(st) of<br>
         (Bottom) -&gt; eos<br>
         (Tree left val right) -&gt;<br>
            case (a &gt; val) of<br>
               True -&gt; return $ (val, right)<br>
               False -&gt; noMatch<br>
<br>
eqT a = do<br>
   make $ \ st -&gt; do<br>
      case(st) of<br>
         (Bottom) -&gt; eos<br>
         (Tree _ val _) -&gt;<br>
            case (a == val) of<br>
               True -&gt; return $ (val, st)<br>
               False -&gt; noMatch<br>
<br>
search a = manyTill (left a &lt;|&gt; right a) (eqT a)<br>
<br>
&gt; run (search 5) $ Tree (Tree Bottom 1 Bottom) 3 (Tree Bottom 5 Bottom)<br>
Right (([3],5),Tree Bottom 5 Bottom)<br>
<div><div></div><div class="h5"><br>
<br>
<br>
On Wed, Sep 30, 2009 at 8:04 PM, Anatoly Yakovenko<br>
&lt;<a href="mailto:aeyakovenko@gmail.com">aeyakovenko@gmail.com</a>&gt; wrote:<br>
&gt; i got annoyed with Parsec and wrote a much more boring parser which<br>
&gt; allows me to parse anything with any kind of matching i want.  Its<br>
&gt; basically a combination of State and Error monads.<br>
&gt;<br>
&gt; So i can use a grep like parser that matches via a regular expression<br>
&gt; over a list of lines<br>
&gt;<br>
&gt; grep re = do<br>
&gt;   vv::B.ByteString &lt;- any<br>
&gt;   let (_,_,_,rv) = (vv =~<br>
&gt; re)::(B.ByteString,B.ByteString,B.ByteString,[B.ByteString])<br>
&gt;   case (rv) of<br>
&gt;      [] -&gt; throwError &quot;no match&quot;<br>
&gt;      _ -&gt; return $ rv<br>
&gt;<br>
&gt;&gt; run (grep $ C.pack &quot;(hello)&quot;) $ [C.pack &quot;hello world&quot;]<br>
&gt; Right ([&quot;hello&quot;],[])<br>
&gt;<br>
&gt; or use the same library to scan over a string by combining regular expressions<br>
&gt;<br>
&gt; regex re = do<br>
&gt;   make $ \ st -&gt; do<br>
&gt;      case (B.null st) of<br>
&gt;         True -&gt; throwError &quot;eos&quot;<br>
&gt;         _ -&gt; do<br>
&gt;            let (_,_,after,rv) = (st =~<br>
&gt; re)::(B.ByteString,B.ByteString,B.ByteString,[B.ByteString])<br>
&gt;            case (rv) of<br>
&gt;               [] -&gt; throwError &quot;no match&quot;<br>
&gt;               _ -&gt; return $ (rv,after)<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;&gt;  run (do aa &lt;- regex $ C.pack &quot;(hello)&quot;; bb &lt;- regex $ C.pack &quot; (world)&quot;; return (aa,bb) ) $ C.pack &quot;hello world&quot;<br>
&gt; Right (([&quot;hello&quot;],[&quot;world&quot;]),&quot;&quot;)<br>
&gt;<br>
&gt; or simply match integers in a list, or anything that is of type Eq<br>
&gt;<br>
&gt;&gt; run (many1 $ eq 1) [1,1,1,2,3,4]<br>
&gt; Right ([1,1,1],[2,3,4])<br>
&gt;<br>
&gt; i can define lt<br>
&gt;<br>
&gt; lt cc = do<br>
&gt;   vv &lt;- any<br>
&gt;   case (vv &lt; cc) of<br>
&gt;      True -&gt; return $ vv<br>
&gt;      _ -&gt; throwError &quot;no match&quot;<br>
&gt;<br>
&gt; and do<br>
&gt;<br>
&gt;&gt; run (many1 $ lt 5 &lt;|&gt; eq 5) [1..10]<br>
&gt; Right ([1,2,3,4,5],[6,7,8,9,10])<br>
&gt;<br>
&gt; here is the implementation<br>
&gt;<br>
&gt; module Parser( ParserM     --type alias for the parser ParserM a b is<br>
&gt; over &quot;stream&quot; a and returns b<br>
&gt;             , make        --makes a parser from a matching function of<br>
&gt; type :: stream -&gt; m (match_data,stream)<br>
&gt;                           --for example any is implemented via:<br>
&gt;                           --any :: ParserM [a] a<br>
&gt;                           --any = make $ \ ll -&gt;<br>
&gt;                           --   case (ll) of<br>
&gt;                           --         (hh:tt) -&gt; return $ (hh,tt)<br>
&gt;                           --               _ -&gt; throwError &quot;eos<br>
&gt;                           --matches and returns an element from a<br>
&gt; list, which makes any of type :: ParserM [a] a<br>
&gt;             , any         --matches any element from [a] type stream<br>
&gt;             , eq          --matches an equal element from [Eq] stream,<br>
&gt; trivialy implemented in terms of any<br>
&gt;                           --eq :: Eq a =&gt; a -&gt; ParserM [a] a<br>
&gt;                           --eq cc = do<br>
&gt;                           --   vv &lt;- any<br>
&gt;                           --   case (vv == cc) of<br>
&gt;                           --      True -&gt; return $ vv<br>
&gt;                           --         _ -&gt; throwError &quot;no match<br>
&gt;             , (&lt;|&gt;)       --or operator, tries the left one then the right one<br>
&gt;             , manyTill    --collects the results of parser 1 until<br>
&gt; parser 2 succeeds<br>
&gt;             , many1       --collects the results of the parser, must<br>
&gt; succeed at least once<br>
&gt;             , many        --collects the results of a parser<br>
&gt;             , run         --runs the parser<br>
&gt;             ) where<br>
&gt;<br>
&gt; import Control.Monad.State.Lazy<br>
&gt; import Control.Monad.Error<br>
&gt; import Test.QuickCheck<br>
&gt; import Control.Monad.Identity<br>
&gt; import Prelude hiding (any)<br>
&gt;<br>
&gt; type ParserM a c = StateT a (ErrorT [Char] Identity) c<br>
&gt;<br>
&gt; make pp = do<br>
&gt;   st &lt;- get<br>
&gt;   (rv,nst) &lt;- pp $ st<br>
&gt;   put $ nst<br>
&gt;   return $ rv<br>
&gt;<br>
&gt; aa &lt;|&gt; bb = aa `catchError` \ _ -&gt; bb<br>
&gt;<br>
&gt; manyTill :: ParserM a c -&gt; ParserM a d -&gt; ParserM a ([c],d)<br>
&gt; manyTill pp ee = do<br>
&gt;   do dd &lt;- ee<br>
&gt;      return $ ([],dd)<br>
&gt;   `catchError` \ _ -&gt; do<br>
&gt;      cc &lt;- pp<br>
&gt;      (ccs,dd) &lt;- manyTill pp ee<br>
&gt;      return $ (cc:ccs,dd)<br>
&gt;<br>
&gt; many1 pp = do<br>
&gt;   rv &lt;- pp<br>
&gt;   rest &lt;- many1 pp `catchError` \ _ -&gt; return $ []<br>
&gt;   return $ rv : rest<br>
&gt;<br>
&gt; many pp = do many1 pp<br>
&gt;         &lt;|&gt; return []<br>
&gt;<br>
&gt;<br>
&gt; any :: ParserM [a] a<br>
&gt; any = make $ \ ll -&gt;<br>
&gt;   case (ll) of<br>
&gt;      (hh:tt) -&gt; return $ (hh,tt)<br>
&gt;      _ -&gt; throwError &quot;eos&quot;<br>
&gt;<br>
&gt; eq :: Eq a =&gt; a -&gt; ParserM [a] a<br>
&gt; eq cc = do<br>
&gt;   vv &lt;- any<br>
&gt;   case (vv == cc) of<br>
&gt;      True -&gt; return $ vv<br>
&gt;      _ -&gt; throwError &quot;no match&quot;<br>
&gt;<br>
&gt; lt cc = do<br>
&gt;   vv &lt;- any<br>
&gt;   case (vv &lt; cc) of<br>
&gt;      True -&gt; return $ vv<br>
&gt;      _ -&gt; throwError &quot;no match&quot;<br>
&gt;<br>
&gt; run pp dd = runIdentity $ runErrorT $ runStateT pp dd<br>
&gt; run&#39; = flip run<br>
&gt;<br>
&gt;<br>
&gt; prop_MatchA = (Right (&#39;a&#39;,&quot;bc&quot;)) == (run&#39; &quot;abc&quot; $ eq &#39;a&#39;)<br>
&gt; prop_MatchEOS = (Left &quot;eos&quot;) == (run&#39; &quot;&quot;  $ eq &#39;a&#39;)<br>
&gt; prop_MatchNoMatch = (Left &quot;no match&quot;) == (run&#39; (&quot;bcd&quot;) $ eq &#39;a&#39;)<br>
&gt;<br>
&gt; prop_MatchABC =(Right (&#39;c&#39;,&quot;&quot;))== (run&#39; &quot;abc&quot; $ do  eq &#39;a&#39;<br>
&gt;                                                    eq &#39;b&#39;<br>
&gt;                                                    eq &#39;c&#39;)<br>
&gt;<br>
&gt; prop_MatchA_C = (run&#39; &quot;abc&quot; $ do eq &#39;a&#39;<br>
&gt;                                 eq &#39;d&#39; &lt;|&gt; eq &#39;b&#39; &lt;|&gt; any<br>
&gt;                                 eq &#39;c&#39;) == (Right (&#39;c&#39;,&quot;&quot;))<br>
&gt;<br>
&gt; prop_Or =      (run&#39; &quot;abc&quot; $ do { eq &#39;a&#39;<br>
&gt;                                ; do     { eq &#39;b&#39;<br>
&gt;                                         ; eq &#39;d&#39;<br>
&gt;                                         }<br>
&gt;                                  &lt;|&gt; do { eq &#39;b&#39;<br>
&gt;                                         ; eq &#39;c&#39;<br>
&gt;                                         }<br>
&gt;                                }) == (Right (&#39;c&#39;,&quot;&quot;))<br>
&gt;<br>
&gt; prop_UntilC = (Right ((&quot;&quot;,&#39;c&#39;),&quot;&quot;)) == (run&#39; (&quot;c&quot;) $ manyTill any $ eq &#39;c&#39;)<br>
&gt;<br>
&gt; prop_Until1 ls =<br>
&gt;   let rv = run&#39; (ls ++ [1]) $ manyTill any $ eq 1<br>
&gt;   in case (rv) of<br>
&gt;      Right ((ls,1),rest) -&gt; (elem 1 ls) == False<br>
&gt;      _ -&gt; False<br>
&gt;<br>
&gt; prop_all1 ls =<br>
&gt;   let rv = run&#39; ([1,1,1] ++ ls) $ many1 $ eq 1<br>
&gt;   in case (rv) of<br>
&gt;      Right (_,(1:_)) -&gt; False<br>
&gt;      Right ((1:1:1:_),_) -&gt; True<br>
&gt;      _ -&gt; False<br>
&gt;<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>