代码之家  ›  专栏  ›  技术社区  ›  M.E.

为什么我在编译一个基本的yacc程序时得到yylex和yyerror的未定义符号?

  •  0
  • M.E.  · 技术社区  · 5 年前

    我正在用yacc/lex编写一个basic程序 undefined symbol error yacc C生成的源代码 yyerror yylex . 如何指定这些文件是在 lex 莱克瑟?

        %{
        
        #include <time.h>
        #include <stdio.h>
        
        %}
        
        %union {
        
                struct tm       datetime;               /* DATE TIME VALUES */
                double          float_number;           /* 8 BYTES DOUBLE VALUE */
                long            integer_number;         /* 8 BYTES INTEGER VALUE */
        
        }
        
        %token  <datetime>              DATETIME
        %token  <float_number>          FLOAT_NUMBER
        %token  <integer_number>        INTEGER_NUMBER
        
        %%
        
        lastbid_lastask:        DATETIME ',' FLOAT_NUMBER ',' FLOAT_NUMBER ',' INTEGER_NUMBER   { printf("MATCH %lf %lf %ld\n", $3, $5, $7); }
                                ;
        
        %%
        
        int main(int argc, char *argv[]) {
        
                yyparse();
        
                return 0;
        
        }
    

    readfile_lexer.l文件

    %{
    
    #include <time.h>
    #include "readfile_grammar.h"
    
    %}
    
    %%
    
                                                                            /* SKIP BLANKS AND TABS */
    [\t ]                                                                   { ; }
    
                                                                            /* YYYYMMDD HHMM DATE */
    [12][09][0-9][0-9][0-1][0-9][0-3][0-9][ ][0-2][0-9][0-5][0-9]           { read_date_YYYYMMDD_HHMM(); return DATETIME; }
    
                                                                            /* FLOAT NUMBER */
    [0-9]+\.[0-9]+                                                          { read_float_number(); return FLOAT_NUMBER; }
    
                                                                            /* INTEGER NUMBER */
    [0-9]+                                                                  { read_integer_number(); return INTEGER_NUMBER; }
    
    %%
    
    /* READ FLOAT NUMBER */
    void read_float_number(void) {
            sscanf(yytext, "%lf", &yylval.float_number);
    }
    
    /* READ INTEGER NUMBER */
    void read_integer_number(void) {
            sscanf(yytext, "%ld", &yylval.integer_number);
    }
    
    /* READ YYYYMMDD HHMM DATE */
    void read_date_YYYYMMDD_HHMM(void) {
    
            /*  DATETIME STRUCT TM */
            struct tm dt;
            char buffer[80];
    
            /* READ VALUES */
            sscanf(yytext, "%4d%2d%2d %2d%2d", &dt.tm_year, &dt.tm_mon, &dt.tm_day, &dt.tm_hour, &dt.tm_min);
    
            /* NORMALIZE VALUES */
            dt.tm_year = dt.tm_year - 1900;         /* NORMALIZE YEAR */
            dt.tm_mon = dt.tm_mon - 1;              /* NORMALIZE MONTH */
            dt.tm_isdst = -1;                       /* NO INFORMATION ABOUT DST */
            mktime(&dt);                            /* NORMALIZE STRUCT TM */
    
            /* PRINT DATETIME */
            strftime(buffer, 80, "%c %z %Z\n", &dt);a
            printf("%s\n", buffer);
    
            /* COPY STRUCT TM TO YACC RETURN VALUE */
            memcpy(&dt, &yylval.datetime, sizeof(dt));
    
    }
    

    CCFLAGS = -std=c89
    YFLAGS = -d     # Forces generation of y.tab.h
    OBJS = readfile_lexer.o readfile_grammar.o
    TARGET = readfile
    
    readfile:               $(OBJS)
                            cc $(OBJS) -std=c89 -lm -o $(TARGET)
    
    readfile_grammar.h readfile_grammar.o:  readfile_grammar.y
                                    yacc $(YFLAGS) -oreadfile_grammar.c readfile_grammar.y
                                    cc $(CCFLAGS) readfile_grammar.c
    
    readfile_lexer.o:               readfile_lexer.l readfile_grammar.h
                                    lex -oreadfile_lexer.c readfile_lexer.l
                                    cc $(CCFLAGS) readfile_lexer.c
    
    clean:
                                    rm -f $(OBJS) readfile_grammar.[ch] readfile_lexer.c
    

    在试图编译源代码时,我得到了上面提到的错误:

    % make
    yacc -d -oreadfile_grammar.c readfile_grammar.y
    cc -std=c89 readfile_grammar.c
    ld: error: undefined symbol: yylex
    >>> referenced by readfile_grammar.c
    >>>               /tmp/readfile_grammar-2d51ee.o:(yyparse)
    
    ld: error: undefined symbol: yyerror
    >>> referenced by readfile_grammar.c
    >>>               /tmp/readfile_grammar-2d51ee.o:(yyparse)
    
    ld: error: undefined symbol: yylex
    >>> referenced by readfile_grammar.c
    >>>               /tmp/readfile_grammar-2d51ee.o:(yyparse)
    
    ld: error: undefined symbol: yyerror
    >>> referenced by readfile_grammar.c
    >>>               /tmp/readfile_grammar-2d51ee.o:(yyparse)
    cc: error: linker command failed with exit code 1 (use -v to see invocation)
    *** Error code 1
    
    Stop.
    
    1 回复  |  直到 5 年前
        1
  •  1
  •   Nate Eldredge    5 年前

    在makefile中,在命令中 cc $(CCFLAGS) readfile_grammar.c -c 选项指定这只是一个模块并应编译为 .o 文件:

    readfile_grammar.h readfile_grammar.o:  readfile_grammar.y
            yacc $(YFLAGS) -oreadfile_grammar.c readfile_grammar.y
            cc -c $(CCFLAGS) readfile_grammar.c
    

    否则,cc假设它是整个程序,并尝试将其链接到可执行的二进制文件中,这当然会失败,因为它调用其他文件中的函数。