6

Tôi muốn bắt đầu một dự án liên quan đến việc chuyển đổi mã C, nhưng tôi muốn bao gồm các chỉ thị tiền xử lý. Tôi không muốn phát minh lại bánh xe bằng cách viết riêng C phân tích cú pháp của tôi, vì vậy không ai biết của một front-end có thể phân tích C Preprocessor và C mã, và tạo ra một AST có thể được sử dụng để tái -generate (hoặc in đẹp) nguồn gốc?Đề nghị C front-end duy trì các chỉ thị tiền xử lý

ví dụ,:.

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

Đoạn mã trên nên được phân tích vào một số đại diện trong bộ nhớ có thể được sử dụng để tái tạo nguồn. Nói cách khác, nó không nên được xử lý như bình thường C trong hai pha, đầu tiên xử lý các chỉ thị PP và sau đó phân tích cú pháp tinh khiết C mã. Thay vào đó, nó sẽ đại diện cho toàn bộ logic biên dịch bao gồm các biến tiền xử lý.

Trả lời

0

Lấy trình biên dịch GNU gcc, các cờ bắt buộc để xử lý trước nguồn là gcc -E mysource.c, xem here để biết thêm thông tin. Đối với khá in ấn nó, có indent và điều này giải thích việc sử dụng here, đây là một chút cũ, nhưng dù sao đáng nói đến. Ngoài ra còn có cflow có thể tạo bản đồ nguồn.

Xin lỗi nếu tôi hiểu sai những gì bạn đang tìm kiếm ...

Hope this helps, Trân trọng, Tom.

+0

Tại sao bạn nên downvote? Tôi đã đề cập đến thụt lề và luồng ... nhưng câu hỏi là không rõ ràng là tại sao AST cần thiết khi bối cảnh của câu hỏi bao gồm 'khá in'. Nó sẽ là tốt đẹp cho một downvote để lại một bình luận giải thích lý do tại sao thay vì bỏ qua nó mà là chống lại tinh thần của SO. – t0mm13b

+0

Tôi không biết tại sao một người nào đó cũng sẽ làm bạn thất vọng. –

+0

Tình trạng downvotes xảy ra; họ là một mối phiền toái. Thông thường, họ không làm thiệt hại không thể khắc phục cho danh tiếng của bạn. –

1

DMS Software Reengineering Toolkita C front end (và C++ cuối phía trước) của chúng tôi rằng:

  • phân tích cú pháp (compilable) mã nguồn C trong một loạt các các phương ngữ thành AST,
  • duy trì các chỉ thị tiền xử lý trong hầu hết các trường hợp như các nút AST
  • có thể tạo lại mã C có thể đồng bộ (có nhận xét và chỉ thị tiền xử lý) từ AST s
  • có thể thu thập hàng ngàn tập tin trong một hình ảnh duy nhất để cho phép phân tích chéo tập tin và chuyển đổi
  • cung cấp đầy đủ xây dựng bảng biểu tượng và truy cập
  • cung cấp truy cập thủ tục để ASTs với một thư viện AST thao tác lớn, bao gồm điều hướng, kiểm tra , chèn, xóa, thay thế, kết hợp, ...
  • cung cấp nguồn-to-nguồn biến đổi sử dụng các mẫu viết bằng các ký hiệu C phù hợp so với ASTs

Đối với C (chưa cho C++), DMS cũng cung cấp:

  • điều khiển và dữ liệu phân tích dòng địa phương và toàn cầu điểm để phân tích
  • xây dựng đồ thị cuộc gọi toàn cầu

DMS đã được sử dụng để xử lý các ứng dụng C cực lớn với mục đích trích xuất các sự kiện và tạo ra mã nguồn mới, có nguồn gốc từ cơ sở nguồn gốc.

(EDIT: Feb 2016)

Nó có thể xử lý ví dụ của OP (với các sửa chữa nhỏ để làm cho nó hợp lệ). Đây là nguồn hơi sửa đổi:

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

} 

Đây là AST sản xuất:

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 
    | |(IDEN[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]C~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 

Bạn có thể thấy các chỉ thị tiền xử lý là "if_directive" trên dòng 8.

Vâng, DMS có thể prettyprint cái cây này nữa. Lệnh sau chạy trình phân tích cú pháp để tạo ra một AST, và sau đó chạy trình gỡ rối DMS để tạo nguồn chỉ từ cây. Chuyến đi khứ hồi là chính xác; bạn có thể biên dịch lại và nhận được kết quả tương tự. Bình luận cũng được bảo tồ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++. Tại thời điểm này, nó xử lý tất cả C++ 14 cho các phương ngữ GCC và MS.

Các vấn đề liên quan