4 Stimmen

C-Frontend empfehlen, das Präprozessoranweisungen beibehält

Ich würde gerne ein Projekt starten, das die Umwandlung von C Code, aber ich würde gerne einschließen. die Präprozessoranweisungen. Ich möchte das Rad nicht neu erfinden, indem ich meine eigene C Parser, kennt also jemand ein Front-End, das Parsing C Präprozessor und C und einen AST-Code erzeugen, der zur Neuerzeugung (oder zum Pretty-Printing) des ursprünglichen Quellcodes verwendet werden kann?

z.B.,:

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

Der obige Code sollte in eine speicherinterne Darstellung geparst werden, die zur Neuerzeugung des Quellcodes verwendet werden kann. Mit anderen Worten, er sollte nicht als normaler Code verarbeitet werden C in zwei Phasen, wobei zunächst die PP-Direktiven verarbeitet werden und dann die reinen C Code. Vielmehr sollte er die gesamte Kompilierzeitlogik einschließlich der Präprozessorvariablen darstellen.

3voto

Matthew Slattery Punkte 43123

Werfen Sie einen Blick auf Clang . (Siehe http://clang.llvm.org/features.html#applications .)

1voto

t0mm13b Punkte 33393

Nehmen wir den GNU gcc-Compiler, so lauten die für die Vorverarbeitung des Quellcodes erforderlichen Flags gcc -E mysource.c siehe aquí für weitere Informationen. Was das hübsche Drucken betrifft, so gibt es Einzug und dies erklärt die Verwendung aquí Dies ist zwar schon etwas älter, aber dennoch erwähnenswert. Es gibt auch cflow die eine Karte der Quelle erstellen kann.

Tut mir leid, wenn ich falsch verstanden habe, wonach Sie suchen...

1voto

Ira Baxter Punkte 91118

Unser DMS-Software-Reengineering-Werkzeugsatz hat ein C-Frontend (und ein C++-Frontend), die:

  • parst (kompilierbaren) C-Quellcode in einer Vielzahl von Dialekten in ASTs,
  • behält die Präprozessoranweisungen in den meisten Fällen als AST-Knoten bei
  • kann kompilierbaren C-Code (mit Kommentaren und Präprozessor-Direktiven) aus den ASTs neu generieren
  • kann Tausende von Dateien in einem einzigen Bild zusammenfassen, um eine dateiübergreifende Analyse und Umwandlung zu ermöglichen
  • bietet vollständige Symboltabellenkonstruktion und -zugriff
  • bietet prozeduralen Zugriff auf ASTs mit einer umfangreichen AST-Manipulationsbibliothek, einschließlich navigieren, inspizieren, einfügen, löschen, ersetzen, abgleichen, ...
  • bietet Quelle-zu-Quelle-Transformationen unter Verwendung von Mustern, die in der C-Notation geschrieben sind und mit den ASTs übereinstimmen

Für C (noch nicht für C++) bietet DMS auch:

  • Kontroll- und Datenflussanalyse
  • lokale und globale Punkt-zu-Punkt-Analyse
  • Konstruktion eines globalen Anrufdiagramms

DMS wurde verwendet, um extrem große C-Anwendungen zu verarbeiten, um Fakten zu extrahieren und neuen, abgeleiteten Code aus der ursprünglichen Quellbasis zu erzeugen.

(EDIT: Feb 2016)

Es kann mit dem Beispiel des Auftraggebers umgehen (mit leichten Korrekturen, um es gültig zu machen). Hier ist der leicht überarbeitete Quelltext:

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

}

Hier ist die AST produziert:

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
(translation_unit@C~GCC4=2#4a7e0e0^0 Line 1 Column 1 File C:/temp/test.c
 (declaration_seq@C~GCC4=605#4a77580^1#4a7e0e0:1 {4} Line 1 Column 1 File C:/temp/test.c
  (control_line@C~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)'#'
   (IDENTIFIER@C~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]
   |(STRING_LITERAL@C~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
   (new_line@C~GCC4=1578#4a77260^1#4a775c0:4[Keyword:0] Line 1 Column 28 File C:/temp/test.c)new_line
  )control_line#4a775c0
  (control_line@C~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)'#'
   (ANGLED_HEADER_NAME@C~GCC4=1589#4a77380^1#4a77460:2[`stdio.h'] Line 2 Column 10 File C:/temp/test.c)ANGLED_HEADER_NAME
   (new_line@C~GCC4=1578#4a773c0^1#4a77460:3[Keyword:0] Line 2 Column 19 File C:/temp/test.c)new_line
  )control_line#4a77460
  (simple_declaration@C~GCC4=631#4a774c0^1#4a77580:3 Line 4 Column 1 File C:/temp/test.c
   (IDENTIFIER@C~GCC4=1531#4a77360^1#4a774c0:1[`FILE'] Line 4 Column 1 File C:/temp/test.c)IDENTIFIER
   (declarator@C~GCC4=850#4a77520^1#4a774c0:2 Line 4 Column 6 File C:/temp/test.c
   |(ptr_operator@C~GCC4=866#4a77560^1#4a77520:1 Line 4 Column 6 File C:/temp/test.c)ptr_operator
   |(IDENTIFIER@C~GCC4=1531#4a77480^1#4a77520:2[`f'] Line 4 Column 7 File C:/temp/test.c)IDENTIFIER
   )declarator#4a77520
  )simple_declaration#4a774c0
  (function_definition@C~GCC4=966#4a77be0^1#4a77580:4 Line 5 Column 1 File C:/temp/test.c
   (direct_declarator@C~GCC4=852#4a77440^1#4a77be0:1 Line 5 Column 1 File C:/temp/test.c
   |(IDENTIFIER@C~GCC4=1531#4a774e0^1#4a77440:1[`main'] Line 5 Column 1 File C:/temp/test.c)IDENTIFIER
   |(parameter_declaration_clause@C~GCC4=900#4a77220^1#4a77440:2 Line 5 Column 6 File C:/temp/test.c)parameter_declaration_clause
   )direct_declarator#4a77440
   (compound_statement@C~GCC4=507#4a77b20^1#4a77be0:2 Line 5 Column 8 File C:/temp/test.c
   |(statement_seq@C~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
   |  (expression_statement@C~GCC4=503#4a7e040^1#4a77680:1 Line 6 Column 3 File C:/temp/test.c
   |   (assignment_expression@C~GCC4=457#4a77f00^1#4a7e040:1 Line 6 Column 3 File C:/temp/test.c
   |   |(assignment_target@C~GCC4=470#4a77a00^1#4a77f00:1 Line 6 Column 3 File C:/temp/test.c
   |   | (IDENTIFIER@C~GCC4=1531#4a77400^2#4a77a00:1#4a77fc0:1[`f'] Line 6 Column 3 File C:/temp/test.c)IDENTIFIER
   |   |)assignment_target#4a77a00
   |   |(INT_LITERAL@C~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
   |  (simple_declaration@C~GCC4=630#4a7e060^1#4a77680:2 Line 6 Column 3 File C:/temp/test.c
   |   (init_declarator@C~GCC4=835#4a77fc0^1#4a7e060:1 Line 6 Column 3 File C:/temp/test.c
   |   |(IDENTIFIER@C~GCC4=1531#4a77400^2... [ALREADY PRINTED] ...)
   |   |(initializer@C~GCC4=983#4a77f60^1#4a77fc0:2 Line 6 Column 4 File C:/temp/test.c
   |   | (INT_LITERAL@C~GCC4=1471#4a77a60^2... [ALREADY PRINTED] ...)
   |   |)initializer#4a77f60
   |   )init_declarator#4a77fc0
   |  )simple_declaration#4a7e060
   | )AMBIGUITY#4a77680
   | (selection_statement@C~GCC4=527#4a77b40^1#4a77d20:2 Line 7 Column 1 File C:/temp/test.c
   |  (IDENTIFIER@C~GCC4=1531#4a7e0c0^1#4a77b40:1[`file_is_open'] Line 7 Column 5 File C:/temp/test.c)IDENTIFIER
   |  (compound_statement@C~GCC4=507#4a77ae0^1#4a77b40:2 Line 7 Column 19 File C:/temp/test.c
   |   (statement@C~GCC4=490#4a7f840^1#4a77ae0:1 Line 8 Column 1 File C:/temp/test.c
   |   |(if_directive@C~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)'#'
   |   | (IDENTIFIER@C~GCC4=1531#4a7ee60^1#4a7f1c0:2[`CAN_OPEN_IT'] Line 8 Column 8 File C:/temp/test.c)IDENTIFIER
   |   | (new_line@C~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
   |   | (expression_statement@C~GCC4=503#4a7f4a0^1#4a77d40:1 Line 9 Column 5 File C:/temp/test.c
   |   |  (assignment_expression@C~GCC4=457#4a7f3c0^1#4a7f4a0:1 Line 9 Column 5 File C:/temp/test.c
   |   |   (assignment_target@C~GCC4=470#4a7eec0^1#4a7f3c0:1 Line 9 Column 5 File C:/temp/test.c
   |   |   |(IDENTIFIER@C~GCC4=1531#4a7eee0^2#4a7eec0:1#4a7f400:1[`f'] Line 9 Column 5 File C:/temp/test.c)IDENTIFIER
   |   |   )assignment_target#4a7eec0
   |   |   (postfix_expression@C~GCC4=201#4a7f2e0^1#4a7f3c0:2 Line 9 Column 9 File C:/temp/test.c
   |   |   |(IDENTIFIER@C~GCC4=1531#4a7f120^2#4a7f2e0:1#4a7f160:1[`fopen'] Line 9 Column 9 File C:/temp/test.c)IDENTIFIER
   |   |   |(expression_list@C~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] ...)
   |   |   |  (STRING_LITERAL@C~GCC4=1525#4a77160^2... [ALREADY PRINTED] ...)
   |   |   |  $VOID$ [Child 3]
   |   |   |  (STRING_LITERAL@C~GCC4=1525#4a7f2c0^1#4a7f300:4[`filename'] Line 1 Column 18 File C:/temp/test.c)STRING_LITERAL
   |   |   |  $VOID$ [Child 5]
   |   |   | )<!MacroCall>#4a7f300
   |   |   | (STRING_LITERAL@C~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
   |   | (simple_declaration@C~GCC4=630#4a7f480^1#4a77d40:2 Line 9 Column 5 File C:/temp/test.c
   |   |  (init_declarator@C~GCC4=835#4a7f400^1#4a7f480:1 Line 9 Column 5 File C:/temp/test.c
   |   |   (IDENTIFIER@C~GCC4=1531#4a7eee0^2... [ALREADY PRINTED] ...)
   |   |   (initializer@C~GCC4=983#4a7f3e0^1#4a7f400:2 Line 9 Column 7 File C:/temp/test.c
   |   |   |(postfix_expression@C~GCC4=201#4a7f160^1#4a7f3e0:1 Line 9 Column 9 File C:/temp/test.c
   |   |   | (IDENTIFIER@C~GCC4=1531#4a7f120^2... [ALREADY PRINTED] ...)
   |   |   | (expression_list@C~GCC4=228#4a7f260^2... [ALREADY PRINTED] ...)
   |   |   |)postfix_expression#4a7f160
   |   |   )initializer#4a7f3e0
   |   |  )init_declarator#4a7f400
   |   | )simple_declaration#4a7f480
   |   |)AMBIGUITY#4a77d40
   |   |(else_directive@C~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)'#'
   |   | (new_line@C~GCC4=1578#4a7f4e0^1#4a7f4c0:2[Keyword:0] Line 10 Column 6 File C:/temp/test.c)new_line
   |   |)else_directive#4a7f4c0
   |   |(expression_statement@C~GCC4=503#4a7f7c0^1#4a7f840:4 Line 11 Column 5 File C:/temp/test.c
   |   | (postfix_expression@C~GCC4=201#4a77ba0^1#4a7f7c0:1 Line 11 Column 5 File C:/temp/test.c
   |   |  (IDENTIFIER@C~GCC4=1531#4a7f640^1#4a77ba0:1[`printf'] Line 11 Column 5 File C:/temp/test.c)IDENTIFIER
   |   |  (STRING_LITERAL@C~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
   |   |(endif_directive@C~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)'#'
   |   | (new_line@C~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

Sie können die Präprozessoranweisungen als "if_directive" in Zeile 8 sehen.

Ja, DMS kann auch diesen Baum hübsch bedrucken. Der folgende Befehl führt den Parser aus, um einen AST zu erzeugen, und lässt dann den DMS-Prettyprinter laufen, um den Quelltext ausschließlich aus dem Baum zu regenerieren. Der Round-Trip ist genau; Sie können neu kompilieren und erhalten das gleiche Ergebnis. Auch die Kommentare bleiben erhalten.

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

Sie können sehen, wie DMS mit C++ umgeht . An diesem Punkt behandelt es alle C++14 für GCC und MS-Dialekte.

-1voto

kiranputtur Punkte 328

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X