Почему я получаю неопределенный символ для yylex и yyerror при компиляции программы basi c ya cc? - PullRequest
0 голосов
/ 14 июля 2020

Я пишу программу basi c с yacc / lex и получаю undefined symbol error в сгенерированном yacc C исходном коде для yyerror и yylex. Как указать, что эти файлы создаются в лексере 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));

}

makefile

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 Ответ

1 голос
/ 14 июля 2020

В вашем make-файле в команде 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 предполагает, что это вся программа, и пытается связать ее с исполняемым двоичным файлом, что, конечно же, терпит неудачу, поскольку вызывает функции, которые находятся в других файлах.

...