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

时间:2011-01-11 13:40:56

标签: yacc lex compiler-construction

我的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源代码?

3 个答案:

答案 0 :(得分:3)

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;}
%%

答案 1 :(得分:2)

您可以从trojanfoe直接回答您的问题 - 您需要包含<stdio.h>来声明函数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
$

这是一个包含设置CFLAGS = -O -std=c99 -Wall -Wextra的makefile的目录。 (这是在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并使其正确。

答案 2 :(得分:0)

包含头文件stdio.h

用于编译 open terminal找到两个文件并输入

lex pos1.l

yacc pos.y

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

./a.out

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