Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Code insertion using antlr and the line directive

I am using antlr to translate a custom language to C++ code. In this language, user can embed C++ code snippets between $code...$endcode directives, that gets inserted into the translated C++code as-is.

I have the following problem: When there is an error in the code snippet I would like the compiler to point to the source file rather than the translated C++ code.

I tried using line directives as follows, but it didn't work:

"foo.custom_laguage"
1 $code
2 ...some c++ code...
3 $endcode

gets translated to

"auto-generated.cpp"
42 #line 2 "foo.custom_language"
43 ...some c++ code...
44 #line __LINE__ __FILE__

This doesn't work, I think because #line directive modifies what gets written by the __LINE__ macro later. How can I set line number back to the actual line number in the translated C++ code? How does antlr do this?

Here is what I want the auto-generated code to look like:

"auto-generated.cpp"
42 #line 2 "foo.custom_language"
43 ...some c++ code...
44 #line 44 "auto-generated.cpp"  //actual line in this file
45 ..some more C++ code ...

edit: I just found out that there is a way to do this in C# language by using a #line default directive: http://msdn.microsoft.com/en-us/library/34dk387t.aspx But couldn't find anything similar for C++

like image 551
Neha Karanjkar Avatar asked Nov 14 '22 04:11

Neha Karanjkar


1 Answers

It's not clear from the question, but you're generating the #line directives yourself given source-line and source-file? I'm sorry, I'm not familiar with Antlr.

Indeed, #line __LINE__ __FILE__ does nothing but assign the __LINE__ macro to itself.

Because of the evaluation semantics of the preprocessor, you can't easily assign the numeric value of __LINE__ to a macro. (You can only define a new macro to map to the macro __LINE__ literally, returning its current value.) But why do you need that? Unless Antlr itself uses the __LINE__ macro, you don't need to restore it to its previous value.

If it is an issue, the most straightforward solution would be to put the raw C++ code in separate include files and forgo the inline embedding. To prevent proliferation of header files, you could use a construct like

$code
#define USE_SNIPPET_FOO
#include "snippets.h"
$endcode

$code
#define USE_SNIPPET_BAR
#include "snippets.h"
$endcode

and in the header, a kind of reverse header guard:

#ifdef USE_SNIPPET_FOO
#undef USE_SNIPPET_FOO
class foo {};

#elif defined USE_SNIPPET_BAR
#undef USE_SNIPPET_BAR
class bar {};

#else
#error no snippet selected
#endif
like image 136
Potatoswatter Avatar answered Dec 05 '22 13:12

Potatoswatter