2011-09-30 15 views
7

Tôi đang sử dụng Bison và Flex để tạo cặp quét/phân tích cú pháp lại nhưng không thể quấn đầu quanh nơi mọi thứ được đưa vào và khai báo.Bison/Flex tuyên bố lộn xộn ... làm thế nào những gì tôi nên bao gồm/tuyên bố ở đâu?

Trước hết, tôi đang sử dụng Flex reentrant vì vậy tôi cần phải vượt qua loại máy quét yyscan_t đầu tiên tới Bison bằng cách khai báo %parse-param {yyscan_t scanner} và sau đó biến Bison chuyển thành Flex bằng cách khai báo %lex-param {yyscan_t scanner}. Nhưng yyscan_t không được Bison tuyên bố vì vậy tôi phải bao gồm tệp tiêu đề máy quét được tạo Flex (mà tôi đặt tên là scanner.flex.h) trong tệp Bison của tôi. Nhưng kể từ khi tập tin Flex của tôi bao gồm tiêu đề Bison của tôi, và tiêu đề Bison của tôi bây giờ bao gồm các tiêu đề Flex, tôi nhận được thông tư bao gồm mà messes lên công cụ theo những cách không thể đoán trước!

Và giả sử tôi muốn thêm vào theo dõi vị trí với %locations trong tệp Bison của tôi và %bison-locations trong tệp Flex của mình. Bây giờ tôi cần phải thay đổi khai báo yyerror và yylex của tôi (có vẻ như tôi phải định nghĩa yylex AGAIN mặc dù nó được định nghĩa trong tiêu đề Flex được tạo nhưng tôi không thể bao gồm, nhớ?) Trong tệp Bison của tôi để bao gồm con trỏ YYLTYPE . Nhưng giờ thì sao? Dường như tuyên bố YYLTYPE mặc định được đặt SAU phần mở đầu được chèn vào và do đó tôi không thể sử dụng YYLTYPE mặc định này trong khai báo yyerror và yylex của tôi.

Tôi nhận ra rằng có rất nhiều cách giải quyết cho những vấn đề này ... nhưng làm thế nào bạn có nghĩa vụ phải làm điều đó đúng cách? Nó hoàn toàn thoát khỏi tôi và điều này chỉ để lại đầu của tôi một mớ hỗn độn ...

Trả lời

4

Ở đầu tệp bison của bạn, bạn cần chuyển tiếp khai báo các giá trị này. Bạn có thể làm điều này trong một tiêu đề phổ biến hoặc trong tập tin mã trước khi bạn bao gồm các tập tin flex và bison. yyscan_t chỉ là một typedef của một void * vì vậy tôi tuyên bố các tham số như void con trỏ để có được nó để làm việc.

CommonHeader.h

int yylex (union YYSTYPE * yyval_param, struct YYLTYPE * yylloc_param, void * yyscanner); 
int yyerror(struct YYLTYPE * yylloc_param, void *scanner, const char *s); 

Ví dụ về yyerror

int yyerror(struct YYLTYPE * yylloc_param, void *scanner, const char *s) 
{ 
    printf("*** Lexical Error %s %d.%d-%d.%d\n", s, 
     yylloc_param->first_line, yylloc_param->first_column, 
     yylloc_param->last_line, yylloc_param->last_column); 
} 
+0

Tôi biết về yyscan_t bị mất hiệu lực * vì vậy tôi đã làm điều đó mặc dù nó cảm thấy một chút như một hack vì nó được cho là mờ đục. Còn về YYLTYPE thì sao? Nó không được khai báo cho đến sau khi phần mở đầu và chuyển tiếp tuyên bố toàn bộ cấu trúc có vẻ hơi nhiều? –

+0

Tại sao việc chuyển tiếp một cấu trúc có vẻ hơi nhiều. Một tùy chọn khác là thêm% định nghĩa vào tệp bison của bạn. Điều này sẽ tạo ra một tập tin tiêu đề mà bạn có thể bao gồm. – Joe

+0

Toàn bộ rắm não trên phần của tôi ... Tôi nghĩ rằng định nghĩa nhưng nói về phía trước tuyên bố. Tôi tạo ra một tệp tiêu đề nhưng không thể được đưa vào tệp Bison vì nó sẽ dẫn đến đệ quy vô hạn kể từ khi Bison tạo tiêu đề không bao gồm bảo vệ (nhưng chúng có bảo vệ chống lại các kiểu định nghĩa lại). Tôi có thể chuyển tiếp khai báo YYLTYPE, như thế này ?: 'struct YYLTYPE;' 'typedef struct YYLTYPE YYLTYPE;' –

1

tình cờ gặp trong khi điều này tìm kiếm cái gì khác.

Câu trả lời là Bison phát ra khai báo nội bộ cho YYLTYPE sau thông số% union. Do đó, đặt các nguyên mẫu hàm và các công cụ khác trong phần mở đầu sau khi liên kết% tránh vấn đề tự khai báo YYLTYPE; điều này là khá OK, Bison cho phép nhiều hơn một phần mở đầu:

%{ 

/* Prologue 1 */ 

%} 

%this 

%that 

%union {} 

%{ 

/* Prologue 2, YYLTYPE declared */ 

%} 

%% 

blah: talk | blah talk 

%%