所以我正在编写一个野牛(没有lex)解析器,现在我想从文件中读取输入代码,并将输出写入另一个文件。
搜索stackoverflow一段时间后,我发现这种方式应该不错。 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++) };
如果找到帮助,将非常好。
答案 0 :(得分:2)
您正在链接库liby
(链接器选项-ly
)。 The Bison manual对此有话要说:
Yacc库包含
yyerror
和main
个功能。
这就是为什么您有main
的多个定义的原因。您提供一个,自由中就有一个。
此外,文档继续说
这些默认实现通常没有用,但是POSIX需要它们。
(添加了强调)
您不需要链接liby 即可构建包含由野牛生成的解析器的程序,通常您不应该这样做。而是提供您自己的main()
和自己的yyerror()
,两者都已完成。
此外,无论是否链接liby,都应提供yyin
的定义,而不仅仅是声明。为此,请从语法文件中的extern
声明中删除yyin
关键字。
您的语法不完整(根本没有规则),%name
指令未记录下来,Bison也无法识别,但是如果我添加了虚拟规则并注释掉{{1} },并结合讨论的其他更改,然后%name
为我生成一个C源文件,该文件可以成功编译为可执行文件(没有liby)。