c-为什么yacc不能解析语法规则的第二行,即使它正确解析了第一行



我想将行解析为以下行:

20191201 170003296,1.102290,1.102470,0

为此,我编写了以下基本的yacc/lix-grammar/lexer:

语法.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 'n' { printf("MATCH %lf %lf %ldn", $3, $5, $7); }
;
%%
int main(int argc, char *argv[]) {
yyparse();
return 0;
}

lexer.l

%{
#include <time.h>
#include "grammar.h"
void read_float_number(void);
void read_integer_number(void);
void read_date_YYYYMMDD_HHMMSSmmm(void);
void yyerror(const char* msg);
%}

%%
                          /* YYYYMMDD HHMMSSmmm DATE */
[12][09][0-9][0-9][0-1][0-9][0-3][0-9][ ][0-2][0-9][0-5][0-9][0-5][0-9][0-9][0-9][0-9]          { read_date_YYYYMMDD_HHMMSSmmm(); return DATETIME; }
                          /* FLOAT NUMBER */
[0-9]+.[0-9]+                                                                                  { read_float_number(); return FLOAT_NUMBER; }
                          /* INTEGER NUMBER */
[0-9]+                                                                                          { read_integer_number(); return INTEGER_NUMBER; }
                          /* PASS ',' CHARACTER */
,                                                                                               { return ','; } 
                          /* PASS 'n' CHARACTER */
n                                                                                              { return 'n'; } 
                          /* PASS UNEXPECTED CHARACTER */
.                                                                                               { return yytext[0]; }

%%
/* READ FLOAT NUMBER */
void read_float_number(void) {
printf("void read_float_number(void)n");
printf("#%s#n", yytext);
sscanf(yytext, "%lf", &yylval.float_number);
printf("%lfn", yylval.float_number);
}
/* READ INTEGER NUMBER */
void read_integer_number(void) {
printf("void read_integer_number(void)n");
printf("#%s#n", yytext);
sscanf(yytext, "%ld", &yylval.integer_number);
printf("%ldn", yylval.integer_number);
}
/* READ YYYYMMDD HHMMSSmmm DATE */
void read_date_YYYYMMDD_HHMMSSmmm(void) {
printf("void read_date_YYYYMMDD_HHMMSSmmm(void)n");
printf("#%s#n", yytext);
/*  DATETIME STRUCT TM */
struct tm dt;
/* READ VALUES */
sscanf(yytext, "%4d%2d%2d %2d%2d%2d", &dt.tm_year, &dt.tm_mon, &dt.tm_mday, &dt.tm_hour, &dt.tm_min, &dt.tm_sec);
/* 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 DATE TIME */
char buffer[80];
strftime(buffer, 80, "%c %Z", &dt);
printf("%sn", buffer);
/* COPY STRUCT TM TO YACC RETURN VALUE */
memcpy(&yylval.datetime, &dt, sizeof(dt));

}
/* YYERROR */
void yyerror(const char* msg) {
fprintf(stderr, "yyerror %sn", msg);
exit(1);
}

生成文件

CCFLAGS = -std=c89 -c
YFLAGS = -d     # Forces generation of y.tab.h
OBJS = lexer.o grammar.o
TARGET = readfile
readfile:               $(OBJS)
cc $(OBJS) -std=c89 -ll -o $(TARGET)
grammar.h grammar.o:    grammar.y
yacc $(YFLAGS) -ogrammar.c grammar.y
cc $(CCFLAGS) grammar.c
lexer.o:                lexer.l grammar.h
lex -olexer.c lexer.l
cc $(CCFLAGS) lexer.c
clean:
rm -f $(OBJS) grammar.[ch] lexer.c

当我测试程序时,我得到了以下行为,第一行被正确解析,但第二行导致yyerror:

% ./readfile 
20191201 170003296,1.102290,1.102470,0
void read_date_YYYYMMDD_HHMMSSmmm(void)
#20191201 170003296#
Sun Dec  1 17:00:03 2019 CET
void read_float_number(void)
#1.102290#
1.102290
void read_float_number(void)
#1.102470#
1.102470
void read_integer_number(void)
#0#
0
MATCH 1.102290 1.102470 0
20191201 170004413,1.102320,1.102470,0
void read_date_YYYYMMDD_HHMMSSmmm(void)
#20191201 170004413#
Sun Dec  1 17:00:04 2019 CET
yyerror syntax error

为什么第二行失败

您的语法只匹配一行。

如果您想匹配多行,请在开头添加:

input: lastbid_lastask
| input lastbid_lastask

或者,如果你很乐意接受空文件(为什么不呢?(

input: /* empty */
| input lastbid_lastask

最新更新