Fixing the preprocessor
David Nolden
david.nolden.kdevelop at art-master.de
Tue May 26 11:52:38 UTC 2009
Am Dienstag 26 Mai 2009 11:26:42 schrieb Christoph Bartoschek:
> Hi,
>
> I try to fix the preprocessor. My target is to correctly parse the
> following code:
>
> #define MA(x) T<x> a
> #define MB(x) T<x>
> #define MC(X) int
> #define MD(X) c
>
> template <typename P1> struct A {};
> template <typename P2> struct T {};
>
> int main(int argc, char ** argv) {
> MA(A<int>);
> A<MB(int)> b;
> MC(a)MD(b);
> MC(a)d;
> }
>
> Currently the output of the preprocessor is:
>
> template <typename P1> struct A {};
> template <typename P2> struct T {};
>
> int main(int argc, char ** argv) {
> T<A<int>> a;
> A<T<int>> b;
> intc;
> intd;
> }
>
> All four declarations are wrong. All are different instances of the same
> error: After preprocessing tokens are not allowed to merge, but kdevelop
> ignores this.
>
> The cpp fixes this by adding spaces where necessary.
>
> What is the best way to handle this in kdevelop?
>
> 1. One solution would be to check upon macro expansion what the last
> character in the output stream is and to also insert a space if necessary.
> This would solve the first three declarations. The last requires a check
> after macro expansion. The check would also need a table of invalid
> character
> combinations. Altogether such a fix would be quite big and ugly.
>
> 2. Another solution would be to always add a space before and after a macro
> expansion. This would produce different output than cpp, but would it cause
> harm?
>
> 3. A third idea: The output stream of the preprocessor consists of a
> splitted string into different substrings. What about having this
> substrings match the tokens of the program? Then further processing steps
> would no longer merge any tokens. This also requires lots of work but seems
> to be quite clean for me.
>
>
> What is your opinion and do you have a better solution for the problem?
>
> Christoph
The best option would probably be just making sure that tokens are not merged
where it's not desired. That is probably the way most close to cpp, although
it would make the "stringified" preprocessor output look the same way it looks
now (Approximately your Idea Nr. 3).
From what I understand it should be like this: Only merge tokens within a
macro expansion and a "##" in between, else always keep them separate.
See pp-scanner.cpp:131, that is where the token merging happens. Now it looks
like this should not be done at all. Instead, this token merging should be
done when encountering a "##" at the beginning.
Another problem though is the whole input text. The input text to the
preprocessor is given in a "fake tokenization": Each character is represented
as an own token. This means that at least one such initial tokenization has to
happen before processing the text.
Actually, since I know the knobs that need to be turned, I thought this would
be easy and fast to implement, so I just took a look at it. Unfortunately it
did cost me a few hours, and at the end it still didn't work. The problem with
this approach: The lexer will still merge consecutive "<" and "<" tokens into
"<<", as those are never merged by the preprocessor, it only creates tokens
for strings. Thus, only 2 of these problems were fixed with this approach.
Now I tried the other approach of inserting whitespaces, and all it took was 3
added "outout << ' ';" in pp-macro-expander to make _all_ your tests succeed,
thus this is probably the better approach given the architecture.
So in short: The problem is fixed now. Thanks for your investigations on this,
and feel free to find/fix more problems on the parser/preprocessor.
Greetings, David
More information about the KDevelop-devel
mailing list