<div dir="ltr"><div>Thanks Malcolm,</div><div><br></div><div>I did consider the two pass approach (and actually having pass 1 returning a stream of tokens annotated with position information)</div>I'm keeping that option open, especially because for speed one might implement the first pass with Attoparsec and the rest with parsec.<div>How would you keep track of macro expansions and source positions in order to provide nice error messages?</div><div>Do you know of anything on hackage that does something similar (either the two pass or the custom stream approach)?</div><div><br></div><div>Again, thanks. I'm still playing with alternatives before implementing the real language (which, for the curious, is SystemVerilog) so my barrier to trying out and benchmark different approaches is at this moment very low.</div><div>And the real goal is to learn Haskell,don't care much if I'll have a full Verilog parser/elaborator; so playing with alternatives is very much useful.</div><div>The language has also interesting features that make compiling separate files in parallel very challenging, so that's another area I want to play with before being too invested.</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 9, 2015 at 2:05 AM, Malcolm Wallace <span dir="ltr"><<a href="mailto:malcolm.wallace@me.com" target="_blank">malcolm.wallace@me.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think what you really need is a two-pass parser. The first parser consumes the input stream, and copies it to the output stream with files inserted, and macros expanded. The second parser consumes the already-preprocessed stream, and does whatever you like with it.<br>
<br>
Regards,<br>
Malcolm<br>
<div><div class="h5"><br>
On 7 Apr 2015, at 17:25, Maurizio Vitale wrote:<br>
<br>
> I need a custom stream that supports insertion of include files and expansions of macros.<br>
> I also want to be able to give nice error messages (think of clang macro-expansion backtrace), so I cannot use the standard trick of concatenating included files and expanded macros to the current input with setInput/getInput (I think I can't maybe there's a way of keeping a more complex "position" and since the use in producing an error backtrac is rare, it migth be worth exploring; if anybody has ideas here, I'm listening)<br>
><br>
> Assuming I need a more compelx stream, this is what I have (Macro and File both have a string argument, but it will be more compicated, a list of expansions for Macro for instance).<br>
><br>
> Is there a better way for doing this?<br>
> What are the performance implications with backtracking? I'll be benchmarking it, but if people see obvious problems, let me know.<br>
><br>
> Thanks a lot,<br>
> Maurizio<br>
><br>
> {-# LANGUAGE FlexibleInstances #-}<br>
> {-# LANGUAGE FlexibleContexts #-}<br>
> {-# LANGUAGE InstanceSigs #-}<br>
> {-# LANGUAGE MultiParamTypeClasses #-}<br>
><br>
> module Parsing where<br>
><br>
> import Text.Parsec<br>
><br>
> type Parser s m = ParsecT s () m<br>
><br>
> data VStream = File String | Macro String deriving Show<br>
><br>
> newtype StreamStack = StreamStack [VStream] deriving Show<br>
><br>
> instance (Monad m) ⇒ Stream VStream m Char where<br>
> uncons ∷ VStream -> m (Maybe (Char, VStream))<br>
> uncons (File (a:as)) = return $ Just (a, File as)<br>
> uncons (File []) = return Nothing<br>
> uncons (Macro (a:as)) = return $ Just (a, File as)<br>
> uncons (Macro []) = return Nothing<br>
><br>
><br>
><br>
> instance (Monad m) => Stream StreamStack m Char where<br>
> uncons (StreamStack []) = return Nothing<br>
> uncons (StreamStack (s:ss)) =<br>
> case uncons s of<br>
> Nothing → uncons $ StreamStack ss<br>
> Just Nothing → uncons $ StreamStack ss<br>
> Just (Just (c, File s')) → return $ Just (c, StreamStack (File s': ss))<br>
> Just (Just (c, Macro s')) → return $ Just (c, StreamStack (Macro s':ss))<br>
><br>
</div></div>> _______________________________________________<br>
> Haskell-Cafe mailing list<br>
> <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
<br>
</blockquote></div><br></div>