首页 > 解决方案 > 为什么我在编译基本的 yacc 程序时会得到 yylex 和 yyerror 的未定义符号?

问题描述

我正在用 yacc/lex 编写一个基本程序,并且我undefined symbol erroryaccC 生成的源代码中得到了一个yyerroryylex. 如何指定这些文件是在lex词法分析器中生成的?

这是我尝试过的:

readfile_grammar.y

    %{
    
    #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.

标签: cyacclexc89

解决方案


在您的 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 假定它是整个程序并尝试将其链接到可执行二进制文件中,这当然会失败,因为它调用了其他文件中的函数。


推荐阅读