gpt4 book ai didi

c - Lex Yacc 解析器卡在 EOF

转载 作者:太空宇宙 更新时间:2023-11-04 04:30:23 25 4
gpt4 key购买 nike

几天来我一直被这个问题困扰,这个解析器也是如此。这个解析器的要点是解析 http 请求,它确实可以,但是当到达请求结束时,解析器进入无限循环。我已经找到从 lex 文件生成的 C 文件中的点,但不知道如何解决这个问题。

我尝试了其他类似问题中建议的以下方法,但没有成功。

bison-end-of-file

lex-flex-scanning-for-the-eof-character

这是我的 lex 文件:

#undef YYLMAX
#define YYLMAX 4096

#include "ssoyacc.h"

#define yylval ssolval
extern YYSTYPE yylval;

#ifdef FLEX_SCANNER
#define YY_INPUT(buf, result, max_size) { int cc = sso_read(); result = (cc == -1) ? YY_NULL : (buf[0] = cc, 1);}
#else /* NO FLEX */
#undef input
#define input() sso_read()
#define unput(cc) sso_unput(cc)
#define yyless(cc) sso_yyless(cc)
#endif /* FLEX */

%}

%p 30000
%n 4000
%e 2000
%a 30000
%k 2500
%o 50000

nondigit [_a-zA-Z]
alfanum [_a-zA-Z0-9]
digit [0-9]
nonzero_digit [1-9]
octal_digit [0-7]
hexadecimal_digit [0-9a-fA-F]

%start HTTP QUERY ARG XML TAG CDAT FORM_PARAM FORM_VALUE

%%

<INITIAL,HTTP>[ ] {
return SP;
}
<INITIAL,HTTP>\r\n {
return CRLF;
}
<HTTP>HTTP\/{digit}\.{digit} {
return HTTP_VERSION;
}
<HTTP>OPTIONS {
return OPTIONS;
}
<HTTP>GET {
return GET;
}
.
.
.
other tags
.
.
.
<FORM_PARAM>\= {
BEGIN(FORM_VALUE);
return IS;
}
<FORM_VALUE>\& {
BEGIN(FORM_PARAM);
return AMPERSAND;
}
<FORM_VALUE>[0-9a-zA-Z\%\+\.\/]* {
if (yyleng < MAX_ARG_LEN)
{
char cc[3];
int ii;
int jj = 0;
for (ii=0;ii<yyleng;ii++)
{
if (yytext[ii] != '%')
{
if (yytext[ii] == '+')
{
yylval.sval[jj++] = ' ';
}
else
{
yylval.sval[jj++] = yytext[ii];
}
}
else
{
strncpy(cc, yytext+ii+1, 2);
cc[2] = 0;
yylval.sval[jj++] = strtol(cc, NULL, 16);
ii+=2;
}
}
yylval.sval[jj] = 0;
return STRING;
}
else
{
return ERROR;
}
}
%%
int ssowrap(void)
{
return 1;
}

void start_http()
{
init_content(); /* initialize content count */
BEGIN(HTTP);
}

void start_urlencoded()
{
BEGIN(FORM_PARAM);
}

void start_xml()
{
BEGIN(XML);
}


int sso_yyless(int count)
{
int i;
if (count>yyleng)
{
return 0;
}
for (i=0;i<yyleng-count;i++)
{
unput(yytext[yyleng-1-i]);
yytext[yyleng-1-i] = '\0';
}
return 0;
}

void allprint(wchar_t cc)
{
if (isprint(cc))
{
fprintf(stdout, "'%c' 0x%x", cc, cc);
}
else
{
fprintf(stdout, "%x", cc);
}
}

void sprint(wchar_t *pc)
{
fprintf(stdout, "%s", pc);
}

执行陷入循环 while (/*CONSTCOND*/1 ) 并在 case YY_END_OF_BUFFER: 中继续进入两次,然后在 case 126 中进入一次: 在 ssolex.c 文件中。 case 126 中声明的行是 lex 文件中的行 %%

/** The main scanner function which does all the work.
*/
YY_DECL
{
yy_state_type yy_current_state;
char *yy_cp, *yy_bp;
int yy_act;

if ( !(yy_init) )
{
(yy_init) = 1;

#ifdef YY_USER_INIT
YY_USER_INIT;
#endif

if ( ! (yy_start) )
(yy_start) = 1; /* first start state */

if ( ! ssoin )
ssoin = stdin;

if ( ! ssoout )
ssoout = stdout;

if ( ! YY_CURRENT_BUFFER ) {
ssoensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
sso_create_buffer(ssoin,YY_BUF_SIZE );
}

sso_load_buffer_state( );
}

{
#line 44 "ssolex.l"


#line 1265 "<stdout>"

while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
yy_cp = (yy_c_buf_p);

/* Support of ssotext. */
*yy_cp = (yy_hold_char);

/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;

yy_current_state = (yy_start);
yy_current_state += YY_AT_BOL();
yy_match:
do
{
YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
(yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 802 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 1067 );

yy_find_action:
yy_act = yy_accept[yy_current_state];
if ( yy_act == 0 )
{ /* have to back up */
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
yy_act = yy_accept[yy_current_state];
}

YY_DO_BEFORE_ACTION;

do_action: /* This label is used only to access EOF actions. */

打印的最后一件事是 Reading a token: 它在 yacc C 文件中,所以我认为问题一定是 lex 中的 EOF 处理。

/* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
yychar = yylex ();
printf("TOKEN %c, %d\n", yychar, yychar);
}

最佳答案

作为rici提到 sso_read 函数没有返回 -1,而是返回 0。此外,EOF 从未达到,因为 tcp 套接字仍按应有的方式打开。感谢 rici 和 Jon Bollinger 帮助解决这个问题!

关于c - Lex Yacc 解析器卡在 EOF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37029051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com