如何编译使用 Yacc 和 Lex 构建的程序?

发布于 2024-10-11 09:53:47 字数 884 浏览 5 评论 0原文

我的 Yacc 源位于 pos.yacc,我的 Lex 源位于 pos1.lex,如图所示。

pos1.lex

%{
#include "y.tab.h"

int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%

pos.yacc

%token DIGIT
%%
s:e {printf("%d\n",$1);}
e:DIGIT {$$=$1;}
|e e "+" {$$=$1+$2;}
|e e "*" {$$=$1*$2;}
|e e "-" {$$=$1-$2;}
|e e "/" {$$=$1/$2;}
;
%%
main() {
  yyparse();
}
yyerror() {
  printf("Error");
}

编译错误

编译时我收到如下错误:

malathy@malathy:~$ cc lex.yy.c  y.tab.c -ly -ll
pos.y: In function ‘yyerror’:
pos.y:16: warning: incompatible implicit declaration of built-in function ‘printf’
pos.y: In function ‘yyparse’:
pos.y:4: warning: incompatible implicit declaration of built-in function ‘printf’

  • 是什么导致了这些错误?
  • 我该如何编译 Lex 和 Yacc 源代码?

My Yacc source is in pos.yacc and my Lex source is in pos1.lex, as shown.

pos1.lex

%{
#include "y.tab.h"

int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%

pos.yacc

%token DIGIT
%%
s:e {printf("%d\n",$1);}
e:DIGIT {$=$1;}
|e e "+" {$=$1+$2;}
|e e "*" {$=$1*$2;}
|e e "-" {$=$1-$2;}
|e e "/" {$=$1/$2;}
;
%%
main() {
  yyparse();
}
yyerror() {
  printf("Error");
}

Compilation errors

While compiling I am getting errors like:

malathy@malathy:~$ cc lex.yy.c  y.tab.c -ly -ll
pos.y: In function ‘yyerror’:
pos.y:16: warning: incompatible implicit declaration of built-in function ‘printf’
pos.y: In function ‘yyparse’:
pos.y:4: warning: incompatible implicit declaration of built-in function ‘printf’

  • What causes those errors?
  • How am I supposed to compile Lex and Yacc source code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一笑百媚生 2024-10-18 09:53:47

printf() 是在 stdio.h 中定义的,因此只需将其包含在 pos1.lex 中的 y.tab.h 上方即可:

%{
#include <stdio.h>
/* Add  ^^^^^^^^^^^ this line */
#include "y.tab.h"

  int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%

printf() is defined in stdio.h so just include it above y.tab.h in pos1.lex:

%{
#include <stdio.h>
/* Add  ^^^^^^^^^^^ this line */
#include "y.tab.h"

  int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%
中二柚 2024-10-18 09:53:47

您可以从 trojanfoe 直接回答您的问题 - 您需要包含 来声明函数 printf()。这在任何提供给 C 编译器的源代码中都是如此。

但是,您还应该注意,Yacc 源代码的常规后缀是 .y(而不是 .yacc),而 Lex 源代码的常规后缀是 .l >(而不是 .lex)。特别是,使用这些后缀意味着 make 将知道如何处理您的源代码,而不必手动编写编译规则。


给定文件 lex.lyacc.ymake 使用以下方法将它们编译为目标代码:

$ make lex.o yacc.o
rm -f lex.c 
lex  -t lex.l > lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
yacc  yacc.y 
mv -f y.tab.c yacc.c
cc -O -std=c99 -Wall -Wextra -c -o yacc.o yacc.c
rm lex.c yacc.c
$

它位于一个带有 makefile 的目录中,该 makefile 设置 <代码>CFLAGS = -O -std=c99 -Wall -Wextra。 (这是在 MacOS X 10.6.6 上。)有时您会看到使用其他类似的规则;特别是,lex 默认生成一个文件 lex.yy.c(至少在 MacOS X 上),并且您经常会看到如下规则:

lex lex.l
mv lex.yy.c lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c

甚至:

lex lex.l
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.yy.c

替代方案有很多。使用 make 就可以了。

You have the direct answer to your question from trojanfoe - you need to include <stdio.h> to declare the function printf(). This is true in any source code presented to the C compiler.

However, you should also note that the conventional suffix for Yacc source is .y (rather than .yacc), and for Lex source is .l (rather than .lex). In particular, using those sufffixes means that make will know what to do with your source, rather than having to code the compilation rules by hand.


Given files lex.l and yacc.y, make compiles them to object code using:

$ make lex.o yacc.o
rm -f lex.c 
lex  -t lex.l > lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
yacc  yacc.y 
mv -f y.tab.c yacc.c
cc -O -std=c99 -Wall -Wextra -c -o yacc.o yacc.c
rm lex.c yacc.c
$

This is in a directory with a makefile that sets CFLAGS = -O -std=c99 -Wall -Wextra. (This was on MacOS X 10.6.6.) You will sometimes see other similar rules used; in particular, lex generates a file lex.yy.c by default (at least on MacOS X), and you'll often see a rule such as:

lex lex.l
mv lex.yy.c lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c

Or even:

lex lex.l
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.yy.c

The alternatives are legion; use make and it gets it right.

小糖芽 2024-10-18 09:53:47

包含头文件stdio.h

进行编译
打开终端找到这两个文件并输入

lex pos1.l

yacc pos.y

cc lex.yy.c y.tab.h -ll

./a.out

您可以按照以下步骤操作。

Include header file stdio.h

for compilation
open terminal locate both files and type

lex pos1.l

yacc pos.y

cc lex.yy.c y.tab.h -ll

./a.out

You can follow these steps.

就此别过 2024-10-18 09:53:47

你只需要保存在文件中
pos1.l 和 pos.y
我希望它能起作用

you just need to save in file
pos1.l and pos.y
I hope it will work

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文