使用Autotools

时间:2018-03-10 02:38:58

标签: bison flex-lexer autotools

我正在尝试编写一个简单的计算器编译器。这个简单的例子取自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",但有人都有效。 :(

1 个答案:

答案 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文件,以免在生成的分发包中省略。

另请注意,即使您不将-ybison一起使用,它(默认情况下)也会将生成的符号表foo.y放入名为foo.tab.h的标头中},而不是foo.h,正如您所期望的那样。