我将回答这个问题,因为它涉及的主题可能会导致学习使用 bison/yacc 的学生以及像 OP 这样正在编译旧代码并且对错误来自何处感到困惑的人感到困惑。
正如cmets中所暗示的,错误与bison根本无关,而是来自bison文件中包含的C代码,但不是bison的人工制品,也不是由bison或yacc over的变化引起的这些年。它们是由多年来 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 的内容,以及如何解决它:
脚注: 可以关闭一些 gcc 错误,或者通过使用#pragma 或控制错误诊断的级别将它们减少为警告,但在这种情况下这是不可能的。 gcc option -Wno-error-implicit-function-declaration is not supported。行:
#pragma GCC diagnostic warning "-Werror-implicit-function-declaration"
(或类似的)也不能消除错误。只是提到它以防有人想知道
Bison 中的类型冲突
许多人在使用 bison/yacc 中的类似代码时确实遇到了 bison 检测到的代码中类型不匹配的问题。可能值得为此添加一些注释以使答案更完整。通常情况下,在解析类似于您的语法的内容时,使用函数dlink、Link、newnode 和attribute 创建一个解析树。树将由一些 struct 组成,并通过指向结构 struct * 的指针链接,如下所示:
struct treeNode {
int item1,item2;
struct treeNode *left;
struct treeNode *right;
};
typedef struct treeNode TREE_NODE;
typedef TREE_NODE *BINARY_TREE;
为了避免前面显示的隐式函数类型的问题,我们可以像这样声明函数的原型:
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);
我们可以把它和你的语法结合起来制作这个文件:
%{
#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 代码中类型冲突的某些方面,这些方面可能会影响刚接触 bison 的用户或采用其他人代码库的用户。