我正在尝试编写一个简单的计算器编译器。这个简单的例子取自Tom Niemann撰写的Lex and Yacc Tutorial第13和14页。
我想为此编译器添加GNU Autotools。
我在这里向您展示文件内容:
pgfs_cmplr.l
:
%{
#include <stdlib.h>
void yyerror(char*);
// #include "pgfs_cmplr.h"
%}
%%
[0-9]+ { yylval = atoi(yytext); return INTEGER; }
[-+\n]+ return *yytext;
[ \t] ;
. yyerror("invalid character");
<<EOF>> { yyterminate(); }
%%
int yywrap(void) {
return 1;
}
pgfs_cmplr.y
:
%{
#include <stdio.h>
int yylex(void);
void yyerror(char*);
%}
%token INTEGER
%%
program:
program expr '\n' { printf("%d\n", $2); }
|
;
expr:
INTEGER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
;
%%
int yyerror(char* s) {
fprintf(stderr, "ERROR: \'%s\' not valid.\n", s);
return 0;
}
int main(int argc, char const *argv[]) {
yyparse();
return 0;
}
Configure.am
,许多行都在...
中:
AC_PREREQ([2.69])
...
AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
AC_LANG_C
AC_PROG_CC_C99
AC_PROG_YACC
AC_PROG_LEX
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
...
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Makefile.am
,许多行都在...
中:
...
ACLOCAL_AMFLAGS = -I m4
AM_YFLAGS = -t -d -v
bin_PROGRAMS = pgfs_cmplr
pgfs_cmplr_SOURCES = src/lab/pgfs_cmplr.y src/lab/pgfs_cmplr.l src/lab/pgfs_cmplr.c
所以当我执行make
时(如上所述),它会抛出:
$ make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-am
depbase=`echo src/lab/pgfs_cmplr.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT src/lab/pgfs_cmplr.o -MD -MP -MF $depbase.Tpo -c -o src/lab/pgfs_cmplr.o src/lab/pgfs_cmplr.c &&\
mv -f $depbase.Tpo $depbase.Po
src/lab/pgfs_cmplr.l:9:3: error: use of undeclared identifier 'yylval'
{ yylval = atoi(yytext); return INTEGER; }
^
src/lab/pgfs_cmplr.l:9:33: error: use of undeclared identifier 'INTEGER'
{ yylval = atoi(yytext); return INTEGER; }
^
2 errors generated.
make[1]: *** [src/lab/pgfs_cmplr.o] Error 1
make: *** [all] Error 2
这是可以预料到的,因为Flex不知道在哪里定义了令牌,因此我在//#include "pgfs_cmplr.h"
的第4行取消注释pgfs_cmplr.l
,最后我再次执行make
,它会抛出此:
$ make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-am
/bin/sh ./ylwrap src/lab/pgfs_cmplr.l lex.yy.c src/lab/pgfs_cmplr.c -- flex
depbase=`echo src/lab/pgfs_cmplr.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT src/lab/pgfs_cmplr.o -MD -MP -MF $depbase.Tpo -c -o src/lab/pgfs_cmplr.o src/lab/pgfs_cmplr.c &&\
mv -f $depbase.Tpo $depbase.Po
src/lab/pgfs_cmplr.l:4:10: fatal error: 'pgfs_cmplr.h' file not found
#include "pgfs_cmplr.h"
^~~~~~~~~~~~~~
1 error generated.
make[1]: *** [src/lab/pgfs_cmplr.o] Error 1
make: *** [all] Error 2
我该怎么做才能解决这个问题?
我尝试过包含"pgfs_cpmplr.tab.h"
,"pgfs_cpmplr.h"
,"y.tab.h"
,但有人都有效。 :(
答案 0 :(得分:0)
Autotools尝试做的一件事是包装各种本地工具,以提供跨平台和工具集一致的行为。在这种情况下,当Autoconf AC_PROG_YACC
选择GNU Bison作为yacc
二进制文件时,它会自动提供-y
标记,以提高与传统yacc
的一致性。 Bison的手册explains表明这个
最重要的是,模仿[s] Yacc的输出文件名约定,这样 解析器实现文件名为y.tab.c,另一个名称 输出称为y.output和y.tab.h。
因此,当您在相关*.y
中的目标来源和-d
中指定YFLAGS
时,您应该期望生成的定义位于名为的文件中y.tab.h
,即使你正在使用Bison而不是真正的YACC。因此y.tab.h
是您应该#include
的文件。您可能还想在BUILT_SOURCES
。
如果您愿意,可以通过将自己的规则编写到Makefile.am
中来生成解析器的C源代码和标头,并仅命名那些,而不是原始.y
来解决此问题。 1}}文件,在您的目标来源中。在这种情况下,您还需要在BUILT_SOURCES
中为两个生成的文件命名,并在.y
中命名EXTRA_SOURCES
文件,以免在生成的分发包中省略。
另请注意,即使您不将-y
与bison
一起使用,它(默认情况下)也会将生成的符号表foo.y
放入名为foo.tab.h
的标头中},而不是foo.h
,正如您所期望的那样。