6

que me gustaría empezar un proyecto que consiste en la transformación de C código, pero me gustaría incluyen las directivas del preprocesador. No quiero reinventar la rueda escribiendo mi propia C analizador, así que ¿alguien sabe de un front-end que puede analizar C preprocesador y código C, y producir un AST que se puede utilizar para volver -generar (o imprimir bastante) la fuente original?Recomendar C front-end que conserva las directivas de preprocesador

por ejemplo,:.

#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 
} 

El código anterior debe ser analizado en alguna representación en memoria que se puede utilizar para volver a generar la fuente. En otras palabras, no se debe procesar como normal C en dos fases, primero procesando las directivas PP y luego analizando el código puro C. Más bien debería representar toda la lógica del tiempo de compilación, incluidas las variables del preprocesador.

Respuesta

0

Tome el compilador GNU gcc, los indicadores necesarios para preprocesar la fuente son gcc -E mysource.c, consulte here para obtener más información. En cuanto a la impresión bonita, hay indent y esto explica el uso here, esto es un poco viejo, pero no obstante vale la pena mencionarlo. También hay cflow que puede producir un mapa de la fuente.

Lo siento si no he entendido bien lo que estás buscando ...

Espero que esto ayude, Saludos, Tom.

+0

¿Por qué el voto a favor? Mencioné sangría y flujo ... pero la pregunta no es clara en cuanto a por qué es necesario el AST cuando el contexto de la pregunta incluía 'letra bonita'. Sería bueno que un votante dejara un comentario explicando por qué en lugar de ignorarlo está en contra del espíritu de SO. – t0mm13b

+0

No tengo idea de por qué alguien podría devolverte el voto tampoco. –

+0

Votos a favor suceden; son una molestia Por lo general, no causan daños irreparables a tu reputación. –

1

Nuestra DMS Software Reengineering Toolkit tiene a C front end (y extremo frontal de C++) que:

  • análisis sintácticos (compilables) de código fuente de C en una variedad de dialectos en AST,
  • conserva las directivas del preprocesador en la mayoría de los casos como nodos AST
  • puede regenerar código C compilable (con comentarios y directivas de preprocesador) de la AST s
  • se recoge miles de archivos en una sola imagen para permitir el análisis entre archivos y transformación
  • proporciona plena construcción de la tabla de símbolos y el acceso
  • proporciona acceso procedimental y AST con una gran biblioteca de manipulación de AST, incluyendo la navegación, para inspeccionar , insertar, eliminar, reemplazar, unir, ...
  • proporciona transformaciones de fuente a fuente utilizando patrones escritos en la notación C que responden contra los ASTs

Para C (todavía no para C++), DMS también proporciona:

  • de control y datos análisis de flujo
  • puntos-a locales y globales análisis
  • construcción gráfica de llamada global

DMS se ha utilizado para procesar aplicaciones C extremadamente grandes con el fin de extraer hechos y generar código nuevo y derivado de la base de la fuente original.

(EDIT: Feb 2016)

Puede manejar el ejemplo de la OP (con ligeras correcciones para que sea válido). Aquí está la fuente ligeramente revisada:

#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 
} 

} 

Aquí es el AST producido:

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 
    | |(assignment_t[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 

Puede ver las directivas del preprocesador como "if_directive" en la línea 8.

Sí, DMS puede prettyprint este árbol, también. El siguiente comando ejecuta el analizador para producir un AST y luego ejecuta la impresora bonita DMS para regenerar la fuente únicamente desde el árbol. El viaje de ida y vuelta es preciso; puedes recompilar y obtener el mismo resultado. Los comentarios se conservan también.

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++. En este punto maneja todos los C++ 14 para dialectos GCC y MS.

Cuestiones relacionadas