2014-01-28 36 views
1

我已經繼承了一些非常古老的野牛代碼,而且我已經處理了一段時間,編譯失敗並帶有許多警告和錯誤,我可以解決的警告,但我看不出如何糾正錯誤。這裏有一個例子:舊的野牛/ flex代碼不能編譯

鑑於這一組定義:

%% 
    pgm: exp      { pgm = $1; } 

    exp: list     { $$ = dlink(newnode(NULL,NULL),$1); } 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3)); } 

    list: rec 
    |  list ',' rec   { $$ = Link($1, $3); } 

    rec: /* null */    { $$ = newnode(NULL, NULL); } 
    |  path 
    |  path '@' NAME   { $$ = attribute($1, $3); } 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 

    path: NAME     { $$ = newnode($1, NULL); } 
    |  path '.' NAME   { $$ = dlink($1, newnode($3, NULL)); } 
    |  path '[' INT ']'  { $$ = dlink($1, newnode($3, $3)); } 
    |  path '[' INT '-' INT ']'{ $$ = dlink($1, newnode($3, $5)); } 

    %% 

被編譯爲:

bison -d -y gram.y 
    gcc -std=c89 -c y.tab.c 

我收到以下錯誤(這只是衆多方法之一):

gram.y: At top level: 
    gram.y:218:1: error: conflicting types for newnode 
    newnode(name, range) 
    ^
    gram.y:49:26: note: previous implicit declaration of newnode was here 
    "exp: list { $$ = dlink(newnode(NULL,NULL),$1); }" 
+2

顯示*聲明* newnode的gram.y部分。規則之前還是之後,它在哪裏? – librik

+0

_「以前的隱式聲明newnode在這裏」_。請參閱**隱式**?這意味着'newnode'永遠不會被_explicitely_聲明,即''y.lex.c'中沒有原型或者它包含的任何頭文件。用這種小背景來回答是不可能的,例如'NAME'的語義類型是什麼? –

回答

2

我會回答這個問題,因爲它涉及的主題可能會導致混淆學生使用野牛/ yacc,以及那些正在編譯舊代碼並且在錯誤來自何處的混淆中的OP。

正如在評論中暗示的那樣,這些錯誤與野牛根本沒有任何關係,而是來自野牛文件中包含的C代碼,但不是野牛的人工製品,也不是由野牛或yacc中的變化引起的這些年來。它們是多年來C編譯器發生變化的原因。現代C編譯器不像以前那樣容忍(更好),特別是在函數調用和參數檢查方面。即使在現代編譯器上選擇選項來實現向後兼容性,當以前的編譯器可能什麼都不說或只給出警告時,它有時仍會產生錯誤。

爲了證明故障是純粹的C,可以做到以下幾點:

Prompt> gcc -c -xc -std=c89 - 
main() { 
#line 49 "gram.y" 
int a = newnode(a,1); 
int * b = newnode(1,1); 
} 
void * 
#line 218 "gram.y" 
newnode(name, range) 
int name, 
range; 
{ 
} 
^Z 
gram.y: In function 'main': 
gram.y:50:12: warning: initialization makes pointer from integer without a cast 
[enabled by default] 

      ^
gram.y: At top level: 
gram.y:218:1: error: conflicting types for 'newnode' 
gram.y:49:10: note: previous implicit declaration of 'newnode' was here 

     ^

可以看到,在C,GCC將輸出相同的錯誤消息的幾行,你所看到的。

有很多的SO關於這個問題,以及如何解決:

腳註:有可能關閉一些海灣合作委員會的錯誤,或通過使用#pragma,或控制錯誤診斷的水平減少他們的警告,但在這種情況下是不可能的。 gcc option -Wno-error-implicit-function-declaration is not supported。該行:

#pragma GCC diagnostic warning "-Werror-implicit-function-declaration" 

(或類似)也不能消除該錯誤。只要提到它在野牛/ yacc的類似的代碼時萬一有人不知道

類型衝突野牛

很多人都有在他們的代碼類型不匹配由野牛發現問題。爲了讓答案更完整,可能值得在這裏添加一些註釋。通常情況下,當解析類似於語法的東西時,會使用函數dlink,Link,newnodeattribute來生成一個分析樹。樹將作出一些struct和鏈接通過指針結構struct *這樣的:

BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
BINARY_TREE newnode(int item1, int item2); 
BINARY_TREE attribute(BINARY_TREE left, int item); 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 

struct treeNode { 
    int item1,item2; 
    struct treeNode *left; 
    struct treeNode *right; 
    }; 

typedef struct treeNode TREE_NODE; 
typedef TREE_NODE  *BINARY_TREE; 

爲了避免前面顯示隱函數類型的問題,我們可以像這樣的功能聲明原型

我們可以用你的語法結合這使此文件:

%{ 
#define NULL 0 
struct treeNode { 
    int item1,item2; 
    struct treeNode *left; 
    struct treeNode *right; 
    }; 

typedef struct treeNode TREE_NODE; 
typedef TREE_NODE  *BINARY_TREE; 

BINARY_TREE pgm; 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
BINARY_TREE newnode(int item1, int item2); 
BINARY_TREE attribute(BINARY_TREE left, int item); 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 
%} 

%token INT NAME 

%% 
pgm: exp      { pgm = $1; } 

exp: list      { $$ = dlink(newnode(NULL,NULL),$1); } 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3)); } 

list: rec 
    |  list ',' rec   { $$ = Link($1, $3); } 

rec: /* null */    { $$ = newnode(NULL, NULL); } 
    |  path 
    |  path '@' NAME   { $$ = attribute($1, $3); } 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 

path: NAME     { $$ = newnode($1, NULL); } 
    |  path '.' NAME   { $$ = dlink($1, newnode($3, NULL)); } 
    |  path '[' INT ']'  { $$ = dlink($1, newnode($3, $3)); } 
    |  path '[' INT '-' INT ']'{ $$ = dlink($1, newnode($3, $5)); } 

%% 

可能是你所擁有的是什麼樣的?如果我們通過bison和gcc來做到這一點,我們會得到很多警告,但它確實會生成代碼。我注意到你說過你有很多警告。也許他們是這樣的:

gram.y: In function 'yyparse': 
gram.y:23:11: warning: assignment makes pointer from integer without a cast [enabled by default] 
pgm: exp      { pgm = $1; } 
     ^
gram.y:25:5: warning: passing argument 2 of 'dlink' makes pointer from integer without a cast [enabled by default] 
exp: list      { $$ = dlink(newnode(NULL,NULL),$1); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:25:18: warning: assignment makes integer from pointer without a cast [enabled by default] 
exp: list      { $$ = dlink(newnode(NULL,NULL),$1); } 
       ^
gram.y:26:5: warning: passing argument 2 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3)); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
gram.y:25:18: warning: assignment makes integer from pointer without a cast [enabled by default] 
exp: list      { $$ = dlink(newnode(NULL,NULL),$1); } 
       ^
gram.y:26:5: warning: passing argument 2 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3 
)); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:26:5: warning: passing argument 1 of 'Link' makes pointer from integer without a cast [enabled by default] 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3 
)); } 
    ^
gram.y:17:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:26:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3 
)); } 
      ^
gram.y:29:5: warning: passing argument 1 of 'Link' makes pointer from integer without a cast [enabled by default] 
    |  list ',' rec   { $$ = Link($1, $3); } 
    ^
gram.y:17:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:29:5: warning: passing argument 2 of 'Link' makes pointer from integer without a cast [enabled by default] 
    |  list ',' rec   { $$ = Link($1, $3); } 
    ^
gram.y:17:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:29:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  list ',' rec   { $$ = Link($1, $3); } 
      ^
gram.y:31:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
rec: /* null */    { $$ = newnode(NULL, NULL); } 
      ^
gram.y:33:5: warning: passing argument 1 of 'attribute' makes pointer from integer without a cast [enabled by default] 
    |  path '@' NAME   { $$ = attribute($1, $3); } 
    ^
gram.y:16:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE attribute(BINARY_TREE left, int item); 
      ^
gram.y:33:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  path '@' NAME   { $$ = attribute($1, $3); } 
      ^
gram.y:34:5: warning: passing argument 1 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:34:5: warning: passing argument 2 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:34:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 
      ^
gram.y:36:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
path: NAME     { $$ = newnode($1, NULL); } 
      ^
gram.y:37:5: warning: passing argument 1 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  path '.' NAME   { $$ = dlink($1, newnode($3, NULL)); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:37:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  path '.' NAME   { $$ = dlink($1, newnode($3, NULL)); } 
      ^
gram.y:38:5: warning: passing argument 1 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  path '[' INT ']'  { $$ = dlink($1, newnode($3, $3)); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:38:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  path '[' INT ']'  { $$ = dlink($1, newnode($3, $3)); } 
      ^
gram.y:39:5: warning: passing argument 1 of 'dlink' makes pointer from integer without a cast [enabled by default] 
    |  path '[' INT '-' INT ']'{ $$ = dlink($1, newnode($3, $5)); } 
    ^
gram.y:14:13: note: expected 'BINARY_TREE' but argument is of type 'YYSTYPE' 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
      ^
gram.y:39:15: warning: assignment makes integer from pointer without a cast [enabled by default] 
    |  path '[' INT '-' INT ']'{ $$ = dlink($1, newnode($3, $5)); } 
      ^

這些可能是野牛的新用戶非常普遍。爲了消除這些警告,有必要告訴野牛如何使用類型來使其生成類型正確的代碼。這是通過向野牛代碼添加更多行來完成的。首先,我們必須告訴它可以通過語法規則的行爲將返回的類型:

%union { 
    BINARY_TREE tVal; 
    int iVal; 
    } 

,然後我們必須告訴它的類型爲個人令牌返回和規則操作:

%token <iVal> NAME INT 
%type <tVal> exp list rec path 

如果我們這些插入到語法文件中的所有錯誤和警告被消除,我們得到:

%{ 
#define NULL 0 
struct treeNode { 
    int item1,item2; 
    struct treeNode *left; 
    struct treeNode *right; 
    }; 

typedef struct treeNode TREE_NODE; 
typedef TREE_NODE  *BINARY_TREE; 

BINARY_TREE pgm; 
BINARY_TREE dlink(BINARY_TREE left, BINARY_TREE right); 
BINARY_TREE newnode(int item1, int item2); 
BINARY_TREE attribute(BINARY_TREE left, int item); 
BINARY_TREE Link(BINARY_TREE left, BINARY_TREE right); 
%} 
%union { 
    BINARY_TREE tVal; 
    int iVal; 
    } 

%token <iVal> NAME INT 
%type <tVal> exp list rec path 

%% 
pgm: exp      { pgm = $1; } 

exp: list      { $$ = dlink(newnode(NULL,NULL),$1); } 
    |  exp ';' list   { $$ = Link($1, dlink(newnode(NULL,NULL),$3)); } 

list: rec 
    |  list ',' rec   { $$ = Link($1, $3); } 

rec: /* null */    { $$ = newnode(NULL, NULL); } 
    |  path 
    |  path '@' NAME   { $$ = attribute($1, $3); } 
    |  path '(' list ')'  { $$ = dlink($1, $3); } 

path: NAME     { $$ = newnode($1, NULL); } 
    |  path '.' NAME   { $$ = dlink($1, newnode($3, NULL)); } 
    |  path '[' INT ']'  { $$ = dlink($1, newnode($3, $3)); } 
    |  path '[' INT '-' INT ']'{ $$ = dlink($1, newnode($3, $5)); } 

%% 

我希望確定一些類型衝突的C代碼,可以影響用戶的方面新的野牛或那些採用別人的代碼庫。

+0

*對答案的Meta評論*:我確實將原始問題標記爲無法回答,因爲我們無法重現問題。 [這個標誌最終超時(連同其他數百個)](http://meta.stackoverflow.com/questions/287165/why-were-my-older-close-flags-aged-away)。這意味着社區認爲它值得回答,所以我做了一個答案。 –

+0

這暗示的不是社區認爲它應該得到答案,而是社區沒有足夠快地審查國旗(或者主持人沒有足夠快地處理隊列)。 –