我會回答這個問題,因爲它涉及的主題可能會導致混淆學生使用野牛/ 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
,newnode
和attribute
來生成一個分析樹。樹將作出一些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代碼,可以影響用戶的方面新的野牛或那些採用別人的代碼庫。
顯示*聲明* newnode的gram.y部分。規則之前還是之後,它在哪裏? – librik
_「以前的隱式聲明newnode在這裏」_。請參閱**隱式**?這意味着'newnode'永遠不會被_explicitely_聲明,即''y.lex.c'中沒有原型或者它包含的任何頭文件。用這種小背景來回答是不可能的,例如'NAME'的語義類型是什麼? –