野牛输出文件编译时“main”的多重定义

Multiple definition of `main' while bison output file compiling

所以我正在编写一个 bison(没有 lex)解析器,现在我想从文件中读取输入代码并将输出写入另一个文件。

在Whosebug上搜索了一段时间,发现这种方式应该不错。 bison.y:

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    extern FILE *yyin;

    int yylex() { return getc(stdin); }
    void yyerror(char *s) {
      fprintf (stderr, "%s\n", s);
    }
    int counter = 1;
    char filename2[10] = "dest.ll";
    FILE *f2;
%}
%name parse

%%

//grammars

%%

int main(int argc, char *argv[]) {
    yyin = fopen(argv[1], "r");
    if (argc > 2)
      f2 = fopen(argv[2], "w");
    else
      f2 = fopen(filename2, "w");
    yyparse();

    return 0;
} 

然后我这样编译:

bison bison.y
cc -ly bison.tab.c

这里是 cc 编译的结果:

/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x960): multiple definition of `main'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/liby.a(main.o):(.text.startup+0x0): first defined here
/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x98c): undefined reference to `yyin'
collect2: error: ld returned 1 exit status

输出 bison.tab.c 文件只有 1 个主文件。 Ofc int/void main 无所谓。你能教我如何正确地做吗?

P.S。顺便说一句,我不想​​向不同的帖子发送垃圾邮件,这里有一个小问题。如何将字符串 (char *) 存储在野牛的 $$ 中?比如我想在遇到int语法后生成一个代码字符串。我有这个错误,找不到答案:

bison.y:94:8: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
 INTNUM: NUMBER | DIGIT INTNUM {$$ = "string"};

bison.y: In function ‘yyparse’:
bison.y:28:15: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
 PROGRAM: EXPRS { fprintf(f2, "%s: string here %d.\n", $$, counter++) };

如果我能找到帮助,那就太好了。

您正在 linking 库 liby(linker 选项 -ly)。 The Bison manual 对此有话要说:

The Yacc library contains default implementations of the yyerror and main functions.

所以这就是为什么你对 main 有多个定义。你提供一个,liby里就有一个

此外,文档继续说

These default implementations are normally not useful, but POSIX requires them.

(强调)

您不需要 link liby 来构建包含 bison-generated 解析器的程序,通常您不应该这样做。相反,请提供您自己的 main() 和您自己的 yyerror(),这两项您都已经完成了。

此外,无论您 link 是否自由,您都需要提供 yyin 定义 ,而不仅仅是声明。为此,请从语法文件中 yyin 的声明中删除 extern 关键字。

你的语法不完整(根本没有规则)并且 %name 指令没有记录并且我的 Bison 无法识别,但是如果我添加一个虚拟规则并注释掉 %name,结合讨论的其他更改,然后 bison 为我生成一个可以成功编译为可执行文件(没有 liby)的 C 源文件。