[cfe-dev] Adding balanced parentheses to statements
Alastair Donaldson
alastair.donaldson at imperial.ac.uk
Tue Jun 23 15:06:59 PDT 2015
On 23/06/2015 22:21, Richard Smith wrote:
> On Tue, Jun 23, 2015 at 2:09 PM, Alastair Donaldson
> <alastair.donaldson at imperial.ac.uk
> <mailto:alastair.donaldson at imperial.ac.uk>> wrote:
>
> Dear Richard
>
> On 23/06/2015 21:55, Richard Smith wrote:
>> On Tue, Jun 23, 2015 at 1:05 PM, Alastair Donaldson
>> <alastair.donaldson at imperial.ac.uk
>> <mailto: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.
>
> Thanks for this suggestion. However, the calls do not fail: all
> the "open" and "close" strings are emitted. They are just not
> balanced. For example, I see this:
>
> open(8)(open(0)open(1)open(7)d close(1)close(0)+
> open(6)(open(2)open(3)open(5)d close(3)close(2)/
> open(4)2)close(5)close(4))close(7)close(6);close(8)
>
> for the expression:
>
> (d + (d / 2))
>
> So you can see that all the opens have matching closes. It's just
> that they are not balanced.
>
> Does this bring anything else to mind?
>
>
> Oh, I see what you mean now. The problem seems to be that you're
> adding the "open" string for the outer statement after the open string
> for its first substatement. Try this:
>
> InsertTextAfter(s->getLocStart(), ...);
> TraverseStmt(s);
> InsertTextAfterToken(s->getLocEnd(), ...);
>
> (or change your first InsertTextAfter to InsertTextBefore).
I opted for your first suggestion, and it worked like a charm - many thanks!
Best wishes
Ally
> Many thanks
>
> Ally
>
>
>
>>
>> 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 <mailto: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/105f9c04/attachment.html>
More information about the cfe-dev
mailing list