2011-09-30 61 views
7

我正在使用Bison和Flex來創建一個可重入的掃描器/解析器對,但無法將我的頭包裹在所有要包含和聲明的位置。Bison/Flex聲明混亂...我應該怎麼包含/聲明哪裏?

首先,我使用的Flex折返所以我需要通過聲明%parse-param {yyscan_t scanner}先通過掃描儀yyscan_t類型野牛,然後讓野牛通過聲明%lex-param {yyscan_t scanner}通過這個彎曲。但是yyscan_t沒有被Bison聲明,所以我必須在我的Bison文件中包含Flex生成的掃描程序頭文件(我將其命名爲scanner.flex.h)。但是因爲我的Flex文件包含了我的Bison頭文件,而且我的Bison頭文件現在包含了Flex頭文件,所以我收到了包含以不可預知的方式混淆了東西的循環文件!

假設我想在我的Flex文件中添加位於我的Bison文件中的%locations和我的Flex文件中的%bison-locations的位置跟蹤。現在我需要改變我的yyerror和我的yylex的聲明(看起來我必須定義yylex AGAIN,即使它在Flex生成的頭文件中定義,但我不能包含它,請記住?)在我的Bison文件中的函數中包含YYLTYPE指針。但是現在呢?看起來默認的YYLTYPE聲明是在插入序言之後放置的,因此我不能在我的yyerror和我的yylex的聲明中使用這個默認的YYLTYPE。

我意識到有很多解決這些問題的方法......但你應該如何正確地做到這一點?它完全逃脫我,這只是讓我的頭一團糟......

回答

4

在你的野牛文件的頂部,你需要轉發宣佈這些值。在包含flex和bison文件之前,可以在通用標題或代碼文件中執行此操作。 yyscan_t只是一個void *的typedef,所以我將這些參數聲明爲void指針以使其工作。

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); 

的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

我知道yyscan_t是void *的,所以我已經做了,雖然感覺有點像黑客攻擊,因爲它應該是不透明的。那麼YYLTYPE呢?直到序言和前向聲明整個結構看起來有點多之後才聲明它? –

+0

爲什麼前向聲明一個結構似乎有點多。另一個選擇是添加%定義到你的野牛文件。這將生成一個可包含的頭文件。 – Joe

+0

我的腦部放屁總是......我想過定義,但是說前向宣告。我生成一個頭文件,但不能包含在Bison文件中,因爲它會導致無限的包含遞歸,因爲Bison生成的頭文件沒有包含保護(但它們確實有防止重新定義類型的警戒)。 我可以轉發,雖然申報YYLTYPE,這樣的事情?: '結構YYLTYPE;'' typedef結構YYLTYPE YYLTYPE;' –

1

的實例過這個而跑來找別的東西。

答案是Bison在%union規範後發出YYLTYPE的內部聲明。因此,在%union之後的序言部分中放置函數原型和其他內容可以避免自己聲明YYLTYPE的問題;這是相當好的,野牛允許多於一個序幕部分:

%{ 

/* Prologue 1 */ 

%} 

%this 

%that 

%union {} 

%{ 

/* Prologue 2, YYLTYPE declared */ 

%} 

%% 

blah: talk | blah talk 

%%