6

Я хотел бы начать проект, который включает в себя трансформирующий C код, но я хотел бы включать директивы препроцессора. Я не хочу изобретать велосипед, написав свой собственный парсер, так что кто-нибудь знает интерфейс, который может разобрать C препроцессор и C код и создать AST, который может быть использован для повторного -генерировать (или красиво-распечатать) исходный источник?Рекомендуют C передний конец, который сохраняет директивы препроцессора

например,:.

#define FILENAME "filename" 
#include <stdio.h> 

FILE *f=0; 
... 
if (file_is_open) { 
#ifdef CAN_OPEN_IT 
    f = fopen(FILENAME, "r"); 
#else 
    printf("Unable to open file.\n"); 
#endif 
} 

Приведенный выше код должен быть проанализирован в некоторое представление в памяти, которая может быть использована для повторной генерации источника. Другими словами, он не должен обрабатываться как нормальный C в две фазы, сначала обрабатывая директивы PP, а затем обрабатывая чистый код C. Скорее, он должен представлять всю логику компиляции, включая препроцессорные переменные.

ответ

0

Возьмите GNU gcc-компилятор, флаги, необходимые для предварительной обработки источника, - gcc -E mysource.c, см. here для получения дополнительной информации. Что касается красивой печати, то есть indent, и это объясняет использование here, это немного устарело, но тем не менее заслуживает упоминания. Существует также cflow, который может создавать карту источника.

Извините, если я не понял, что вы ищете ...

Надеются, что это помогает, С наилучшими пожеланиями, Том.

+0

Почему downvote? Я упомянул отступ и cflow ... но вопрос не совсем ясен, почему АСТ необходим, когда контекст вопроса включал «симпатичную печать». Было бы неплохо, если бы нижний план оставил комментарий, объясняющий, почему вместо того, чтобы игнорировать его, что противоречит духу SO. – t0mm13b

+0

Я понятия не имею, почему кто-то мог бы сжать вас тоже. –

+0

Случаи слуха; они неприятны. Обычно они не наносят непоправимого ущерба вашей репутации. –

-1

Берет можно посмотреть на http://www.antlr.org/wiki/display/ANTLR3/ANTLR3+Code+Generation+-+C

+1

Это, по-видимому, о генераторах парсеров ANTLR, которые производят синтаксические анализаторы, реализованные в C. OP хочет что-то, что * анализирует * C. Я что-то пропустил? –

1

Нашего DMS Software Reengineering Toolkit имеет a C front end (и C++ переднего конца), что:

  • разбирает (компилируется) С кодом в различном диалекты в АСТ,
  • сохраняет директивы препроцессора в большинстве случаев как узлы AST
  • может регенерировать компилируемый код C (с комментариями и инструкциями препроцессора) из AST s
  • может собирает тысячи файлов в одном изображении, чтобы анализ кросс-файлов и преобразование
  • обеспечивает полное построение таблицы символов и доступа
  • обеспечивает процедурный доступ к НРХ с большой библиотекой манипуляции AST, в том числе навигации, инспектировать , вставить, удалить, заменить, сопоставить, ...
  • обеспечивает от источника до источника преобразования с использованием шаблонов, написанных в обозначениях C, которые соответствуют против НРХ

Для C (еще не для C++), DMS также обеспечивает:

  • контроль и данные анализ потока
  • локальные и глобальные точки-к анализу
  • глобальный граф вызовов строительство

DMS используется для обработки чрезвычайно больших приложений C с целью извлечения фактов и создания нового производного кода из исходной исходной базы.

(EDIT: æÅ 2016)

Он может обрабатывать примеру OP в (с небольшими исправлениями, чтобы сделать его действительным). Вот несколько пересмотрела источник:

#define FILENAME "filename" 
#include <stdio.h> 

FILE *f; 
main() { 
    f=0; 
if (file_is_open) { 
#ifdef CAN_OPEN_IT 
f = fopen(FILENAME, "r"); 
#else 
printf("Unable to open file.\n"); 
#endif 
} 

} 

Вот АСТ произведено:

C~GCC4 Domain Parser Version 3.0.1(28449) 
Copyright (C) 1996-2013 Semantic Designs, Inc; All Rights Reserved; SD Confidential 
Powered by DMS (R) Software Reengineering Toolkit 
AST Optimizations: remove constant tokens, remove unary productions, compact sequences 
Using encoding Unicode-UTF-8?ANSI +CRLF +1 /^I 
([email protected]~GCC4=2#4a7e0e0^0 Line 1 Column 1 File C:/temp/test.c 
([email protected]~GCC4=605#4a77580^1#4a7e0e0:1 {4} Line 1 Column 1 File C:/temp/test.c 
    ([email protected]~GCC4=1094#4a775c0^1#4a77580:1 Line 1 Column 1 File C:/temp/test.c 
    ('#'@C~GCC4=1548#4a771c0^1#4a775c0:1[Keyword:0] Line 1 Column 1 File C:/temp/test.c)'#' 
    ([email protected]~GCC4=1531#4a77200^1#4a775c0:2[`FILENAME'] Line 1 Column 9 File C:/temp/test.c)IDENTIFIER 
    (<!MacroDefinition>@C~GCC4=1603#4a77180^2#4a775c0:3#4a7f300:1[`FILENAME'] Line 1 Column 18 File C:/temp/test.c 
$VOID$ [Child 1] 
    |([email protected]~GCC4=1525#4a77160^2#4a77180:2#4a7f300:2[`filename'] Line 1 Column 18 File C:/temp/test.c)STRING_LITERAL 
$VOID$ [Child 3] 
    )<!MacroDefinition>#4a77180 
    ([email protected]~GCC4=1578#4a77260^1#4a775c0:4[Keyword:0] Line 1 Column 28 File C:/temp/test.c)new_line 
)control_line#4a775c0 
    ([email protected]~GCC4=1104#4a77460^1#4a77580:2 Line 2 Column 1 File C:/temp/test.c 
    ('#'@C~GCC4=1548#4a77340^1#4a77460:1[Keyword:0] Line 2 Column 1 File C:/temp/test.c)'#' 
    ([email protected]~GCC4=1589#4a77380^1#4a77460:2[`stdio.h'] Line 2 Column 10 File C:/temp/test.c)ANGLED_HEADER_NAME 
    ([email protected]~GCC4=1578#4a773c0^1#4a77460:3[Keyword:0] Line 2 Column 19 File C:/temp/test.c)new_line 
)control_line#4a77460 
    ([email protected]~GCC4=631#4a774c0^1#4a77580:3 Line 4 Column 1 File C:/temp/test.c 
    ([email protected]~GCC4=1531#4a77360^1#4a774c0:1[`FILE'] Line 4 Column 1 File C:/temp/test.c)IDENTIFIER 
    ([email protected]~GCC4=850#4a77520^1#4a774c0:2 Line 4 Column 6 File C:/temp/test.c 
    |([email protected]~GCC4=866#4a77560^1#4a77520:1 Line 4 Column 6 File C:/temp/test.c)ptr_operator 
    |([email protected]~GCC4=1531#4a77480^1#4a77520:2[`f'] Line 4 Column 7 File C:/temp/test.c)IDENTIFIER 
    )declarator#4a77520 
)simple_declaration#4a774c0 
    ([email protected]~GCC4=966#4a77be0^1#4a77580:4 Line 5 Column 1 File C:/temp/test.c 
    ([email protected]~GCC4=852#4a77440^1#4a77be0:1 Line 5 Column 1 File C:/temp/test.c 
    |([email protected]~GCC4=1531#4a774e0^1#4a77440:1[`main'] Line 5 Column 1 File C:/temp/test.c)IDENTIFIER 
    |([email protected]~GCC4=900#4a77220^1#4a77440:2 Line 5 Column 6 File C:/temp/test.c)parameter_declaration_clause 
    )direct_declarator#4a77440 
    ([email protected]~GCC4=507#4a77b20^1#4a77be0:2 Line 5 Column 8 File C:/temp/test.c 
    |([email protected]~GCC4=511#4a77d20^1#4a77b20:1 {2} Line 6 Column 3 File C:/temp/test.c 
    | (AMBIGUITY<statement=358>@C~GCC4=1602#4a77680^1#4a77d20:1{2} Line 6 Column 3 File C:/temp/test.c 
    | ([email protected]~GCC4=503#4a7e040^1#4a77680:1 Line 6 Column 3 File C:/temp/test.c 
    | ([email protected]~GCC4=457#4a77f00^1#4a7e040:1 Line 6 Column 3 File C:/temp/test.c 
    | |([email protected]~GCC4=470#4a77a00^1#4a77f00:1 Line 6 Column 3 File C:/temp/test.c 
    | | ([email protected]~GCC4=1531#4a77400^2#4a77a00:1#4a77fc0:1[`f'] Line 6 Column 3 File C:/temp/test.c)IDENTIFIER 
    | |)assignment_target#4a77a00 
    | |([email protected]~GCC4=1471#4a77a60^2#4a77f00:2#4a77f60:1[0] Line 6 Column 5 File C:/temp/test.c)INT_LITERAL 
    | )assignment_expression#4a77f00 
    | )expression_statement#4a7e040 
    | ([email protected]~GCC4=630#4a7e060^1#4a77680:2 Line 6 Column 3 File C:/temp/test.c 
    | ([email protected]~GCC4=835#4a77fc0^1#4a7e060:1 Line 6 Column 3 File C:/temp/test.c 
    | |([email protected]~GCC4=1531#4a77400^2... [ALREADY PRINTED] ...) 
    | |([email protected]~GCC4=983#4a77f60^1#4a77fc0:2 Line 6 Column 4 File C:/temp/test.c 
    | | ([email protected]~GCC4=1471#4a77a60^2... [ALREADY PRINTED] ...) 
    | |)initializer#4a77f60 
    | )init_declarator#4a77fc0 
    | )simple_declaration#4a7e060 
    |)AMBIGUITY#4a77680 
    | ([email protected]~GCC4=527#4a77b40^1#4a77d20:2 Line 7 Column 1 File C:/temp/test.c 
    | ([email protected]~GCC4=1531#4a7e0c0^1#4a77b40:1[`file_is_open'] Line 7 Column 5 File C:/temp/test.c)IDENTIFIER 
    | ([email protected]~GCC4=507#4a77ae0^1#4a77b40:2 Line 7 Column 19 File C:/temp/test.c 
    | ([email protected]~GCC4=490#4a7f840^1#4a77ae0:1 Line 8 Column 1 File C:/temp/test.c 
    | |([email protected]~GCC4=1088#4a7f1c0^1#4a7f840:1 Line 8 Column 1 File C:/temp/test.c 
    | | ('#'@C~GCC4=1548#4a7f240^1#4a7f1c0:1[Keyword:0] Line 8 Column 1 File C:/temp/test.c)'#' 
    | | ([email protected]~GCC4=1531#4a7ee60^1#4a7f1c0:2[`CAN_OPEN_IT'] Line 8 Column 8 File C:/temp/test.c)IDENTIFIER 
    | | ([email protected]~GCC4=1578#4a7f1e0^1#4a7f1c0:3[Keyword:0] Line 8 Column 19 File C:/temp/test.c)new_line 
    | |)if_directive#4a7f1c0 
    | |(AMBIGUITY<statement=358>@C~GCC4=1602#4a77d40^1#4a7f840:2{2} Line 9 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=503#4a7f4a0^1#4a77d40:1 Line 9 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=457#4a7f3c0^1#4a7f4a0:1 Line 9 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=470#4a7eec0^1#4a7f3c0:1 Line 9 Column 5 File C:/temp/test.c 
    | | |([email protected]~GCC4=1531#4a7eee0^2#4a7eec0:1#4a7f400:1[`f'] Line 9 Column 5 File C:/temp/test.c)IDENTIFIER 
    | | )assignment_target#4a7eec0 
    | | ([email protected]~GCC4=201#4a7f2e0^1#4a7f3c0:2 Line 9 Column 9 File C:/temp/test.c 
    | | |([email protected]~GCC4=1531#4a7f120^2#4a7f2e0:1#4a7f160:1[`fopen'] Line 9 Column 9 File C:/temp/test.c)IDENTIFIER 
    | | |([email protected]~GCC4=228#4a7f260^2#4a7f2e0:2#4a7f160:2 Line 9 Column 15 File C:/temp/test.c 
    | | | (<!MacroCall>@C~GCC4=1607#4a7f300^1#4a7f260:1[`FILENAME'] Line 9 Column 15 File C:/temp/test.c 
    | | | (<!MacroDefinition>@C~GCC4=1603#4a77180^2... [ALREADY PRINTED] ...) 
    | | | ([email protected]~GCC4=1525#4a77160^2... [ALREADY PRINTED] ...) 
    | | | $VOID$ [Child 3] 
    | | | ([email protected]~GCC4=1525#4a7f2c0^1#4a7f300:4[`filename'] Line 1 Column 18 File C:/temp/test.c)STRING_LITERAL 
    | | | $VOID$ [Child 5] 
    | | |)<!MacroCall>#4a7f300 
    | | | ([email protected]~GCC4=1525#4a7f140^1#4a7f260:2[`r'] Line 9 Column 25 File C:/temp/test.c)STRING_LITERAL 
    | | |)expression_list#4a7f260 
    | | )postfix_expression#4a7f2e0 
    | | )assignment_expression#4a7f3c0 
    | |)expression_statement#4a7f4a0 
    | | ([email protected]~GCC4=630#4a7f480^1#4a77d40:2 Line 9 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=835#4a7f400^1#4a7f480:1 Line 9 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=1531#4a7eee0^2... [ALREADY PRINTED] ...) 
    | | ([email protected]~GCC4=983#4a7f3e0^1#4a7f400:2 Line 9 Column 7 File C:/temp/test.c 
    | | |([email protected]~GCC4=201#4a7f160^1#4a7f3e0:1 Line 9 Column 9 File C:/temp/test.c 
    | | | ([email protected]~GCC4=1531#4a7f120^2... [ALREADY PRINTED] ...) 
    | | | ([email protected]~GCC4=228#4a7f260^2... [ALREADY PRINTED] ...) 
    | | |)postfix_expression#4a7f160 
    | | )initializer#4a7f3e0 
    | | )init_declarator#4a7f400 
    | |)simple_declaration#4a7f480 
    | |)AMBIGUITY#4a77d40 
    | |([email protected]~GCC4=1091#4a7f4c0^1#4a7f840:3 Line 10 Column 1 File C:/temp/test.c 
    | | ('#'@C~GCC4=1548#4a7f500^1#4a7f4c0:1[Keyword:0] Line 10 Column 1 File C:/temp/test.c)'#' 
    | | ([email protected]~GCC4=1578#4a7f4e0^1#4a7f4c0:2[Keyword:0] Line 10 Column 6 File C:/temp/test.c)new_line 
    | |)else_directive#4a7f4c0 
    | |([email protected]~GCC4=503#4a7f7c0^1#4a7f840:4 Line 11 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=201#4a77ba0^1#4a7f7c0:1 Line 11 Column 5 File C:/temp/test.c 
    | | ([email protected]~GCC4=1531#4a7f640^1#4a77ba0:1[`printf'] Line 11 Column 5 File C:/temp/test.c)IDENTIFIER 
    | | ([email protected]~GCC4=1525#4a77c20^1#4a77ba0:2[`Unable to open file. 
'] Line 11 Column 12 File C:/temp/test.c)STRING_LITERAL 
    | |)postfix_expression#4a77ba0 
    | |)expression_statement#4a7f7c0 
    | |([email protected]~GCC4=1092#4a7f7e0^1#4a7f840:5 Line 12 Column 1 File C:/temp/test.c 
    | | ('#'@C~GCC4=1548#4a7f720^1#4a7f7e0:1[Keyword:0] Line 12 Column 1 File C:/temp/test.c)'#' 
    | | ([email protected]~GCC4=1578#4a7f700^1#4a7f7e0:2[Keyword:0] Line 12 Column 7 File C:/temp/test.c)new_line 
    | |)endif_directive#4a7f7e0 
    | )statement#4a7f840 
    | )compound_statement#4a77ae0 
    |)selection_statement#4a77b40 
    |)statement_seq#4a77d20 
    )compound_statement#4a77b20 
)function_definition#4a77be0 
)declaration_seq#4a77580 
)translation_unit#4a7e0e0 

Вы можете увидеть директивы препроцессора, как "if_directive" на линии 8.

Да, DMS может prettyprint это дерево тоже. Следующая команда запускает синтаксический анализатор для создания AST, а затем запускает дескриптор DMS для регенерации источника исключительно из дерева. Поездка в оба конца точна; вы можете перекомпилировать и получить тот же результат. Замечания сохраняются.

C:\DMS\Domains\C\GCC4\Tools\PrettyPrinter>run domainprettyprinter \temp\test.c 
C~GCC4 PrettyPrinter Version 1.2.13 
Copyright (C) 2004-2013 Semantic Designs, Inc; All Rights Reserved; SD Confidential 
Powered by DMS (R) Software Reengineering Toolkit 

#define FILENAME "filename" 
#include <stdio.h> 
FILE *f; 

main() 
{ 
    f = 0; 
    if (file_is_open) 
    { 
     #ifdef CAN_OPEN_IT 
     f = fopen(FILENAME, "r"); 
     #else 
     printf("Unable to open file.\n"); 
     #endif 
    } 
} 

You can see how DMS handles C++. В этот момент он обрабатывает все C++ 14 для GCC и MS-диалектов.

 Смежные вопросы

  • Нет связанных вопросов^_^