[cfe-dev] Adding balanced parentheses to statements

Richard Smith richard at metafoo.co.uk
Tue Jun 23 13:55:37 PDT 2015


On Tue, Jun 23, 2015 at 1:05 PM, Alastair Donaldson <
alastair.donaldson at imperial.ac.uk> wrote:

> Dear all
>
> I am trying to use the Rewriter class to do something conceptually pretty
> straightforward to a source file.  What I actually want to do is pretty
> specific, but if I could work out how to do the following it would be
> obvious how to solve my problem:
>
> - for every Stmt node in the AST, replace the source code associated with
> the Stmt with:
>
>     open(x) original_source_code_for_Stmt close(x)
>
> where x is a number chosen uniquely for the Stmt node.
>
> For instance, if the Stmt is the expression:
>
> x + y
>
> then I would like to end up with something like:
>
> open(2) open(0) x close(0) + open(1) y close(1) close(2)
>
> I hope my objective makes sense.
>
> What I've tried to do is write a class that extends RecursiveASTVisitor,
> equipped with a Rewriter field, "TheRewriter", and an int field,
> "counter".  The Rewriter should allow me to rewrite the source code.  The
> counter is used to give each open and close a unique x.  I'm assuming for
> now that all my code is in one source file.
>
> I've tried two things:
>
>   bool TraverseStmt(Stmt *s) {
>     bool result = RecursiveASTVisitor::TraverseStmt(s);
>     std::stringstream ss_start;
>     ss_start << "open(" << counter << ")";
>     TheRewriter.InsertTextAfter(s->getLocStart(), ss_start.str());
>     std::stringstream ss_end;
>     ss_end << "close(" << counter << ")";
>     TheRewriter.InsertTextAfterToken(s->getLocEnd(), ss_end.str());
>

InsertTextAfter and InsertTextAfterToken return a bool indicating whether
the insertion was possible (false on success, true on failure). You could
use that to isolate which particular call is failing.

That said, the only cases where the above calls would currently fail are if
they're given a location for which TheRewriter.isRewritable returns false.
That only happens if the location provided is within a macro expansion.
Could that be the case in your failing examples?


>     counter++;
>     return result;
>   }
>
> (This is what seemed natural to me from the clang APIs)
>
> and also:
>
>   bool TraverseStmt(Stmt *s) {
>     bool result = RecursiveASTVisitor::TraverseStmt(s);
>     std::stringstream ss_start;
>     ss_start << "open(" << counter << ")";
>     TheRewriter.InsertTextAfter(s->getLocStart(), ss_start.str());
>     int offset = Lexer::MeasureTokenLength(s->getLocEnd(),
> TheRewriter.getSourceMgr(), TheRewriter.getLangOpts()) + 1;
>     auto END1 = s->getLocEnd().getLocWithOffset(offset);
>     std::stringstream ss_end;
>     ss_end << "close(" << counter << ")";
>     TheRewriter.InsertTextBefore(END1, ss_end.str());
>     counter++;
>     return result;
>   }
>
> (I came up with this after reading this source code from Robert Ankeney:
> https://github.com/loarabia/Clang-tutorial/blob/master/CIrewriter.cpp)
>
> However, neither work - my parentheses end up being unbalanced.
>
> I think the problem may be that in an expression such as:
>
> x + y
>
> the sub-expressions "y" and "x + y" have the same end source location.
> But I cannot figure out how to get around this.
>
> I'd be really grateful if anyone can give me a pointer here.
>
> Best wishes
>
> Ally Donaldson
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150623/2d4b43ff/attachment.html>


More information about the cfe-dev mailing list