gpt4 book ai didi

c - Flex,连续扫描流(来自套接字)。我是否错过了使用 yywrap() 的内容?

转载 作者:太空狗 更新时间:2023-10-29 16:12:26 25 4
gpt4 key购买 nike

使用 Flex 进行模式识别处理基于套接字的扫描仪(连续流)。 Flex 找不到与“数组边界”重叠的匹配项。所以我实现了 yywrap() 以在 yylex() 检测到 <> 时设置新的数组内容(它将调用 yywrap)。至今没有成功。

基本上(为了指出我的问题)这是我的代码:

%{

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUFFERSIZE 26
/* 0123456789012345678901234 */
char cbuf1[BUFFERSIZE] = "Hello everybody, lex is su"; // Warning, no '\0'
char cbuf2[BUFFERSIZE] = "per cool. Thanks! ";
char recvBuffer[BUFFERSIZE];

int packetCnt = 0;

YY_BUFFER_STATE bufferState1, bufferState2;

%}

%option nounput
%option noinput

%%

"super" { ECHO; }
. { printf( "%c", yytext[0] );}

%%

int yywrap()
{

int retval = 1;

printf(">> yywrap()\n");

if( packetCnt <= 0 ) // Stop after 2
{
// Copy cbuf2 into recvBuffer
memcpy(recvBuffer, cbuf2, BUFFERSIZE);

//
yyrestart(NULL); // ?? has no effect

// Feed new data to flex
bufferState2 = yy_scan_bytes(recvBuffer, BUFFERSIZE);

//
packetCnt++;

// Tell flex to resume scanning
retval = 0;
}

return(retval);
}

int main(void)
{
printf("Lenght: %d\n", (int)sizeof(recvBuffer)) ;

// Copy cbuf1 into recvBuffer
memcpy(recvBuffer, cbuf1, BUFFERSIZE);

//
packetCnt = 0;

//
bufferState1 = yy_scan_bytes(recvBuffer, BUFFERSIZE);

//
yylex();

yy_delete_buffer(bufferState1);
yy_delete_buffer(bufferState2);

return 0;
}

这是我的输出:
dkmbpro:test dkroeske$ ./text 
Lenght: 26
Hello everybody, lex is su>> yywrap()
per cool. Thanks! >> yywrap()

所以没有匹配“ super ”。根据文档,词法分析器在 yywrap 之间没有“重置”。我想念什么?谢谢。

最佳答案

flex 提供输入流的机制是提供 YY_INPUT 的定义宏,每次调用flex需要重新填充其缓冲区 [注 1]。使用三个参数调用宏,大致如下:

YY_INPUT(buffer, &bytes_read, max_bytes)

宏预计读取到 max_bytes进入 buffer , 并设置 bytes_read到实际读取的字节数。如果此流中没有更多输入, YY_INPUT应该设置 bytes_readYY_NULL (即 0)。除了设置文件结束条件之外,没有其他方法可以标记输入错误。不要设置 YY_INPUT为负值。

请注意 YY_INPUT不提供从何处读取输入或任何类型的 userdata 的指示争论。唯一提供的机制是全局 yyin ,这是一个 FILE* . (您可以使用 FILE* 从文件/套接字描述符创建 fdopen 并使用 fileno 取回描述符。其他解决方法超出了此答案的范围。)

当扫描程序遇到流的结尾时,如 YY_INPUT 所示返回 0,结束当前 token [注 2],然后调用 yywrap决定是否有另一个流要处理。正如手册所示,它不会重置解析器状态(即,它恰好处于哪个启动条件;如果启用了行计数,则为当前行号等)。但是, 它不允许 token 跨越两个流。
yywrap当解析器/扫描器应用于命令行上指定的许多不同文件时,最常使用该机制。在那个用例中,如果一个 token 可以从一个文件开始并继续到另一个文件,那就有点奇怪了。大多数语言实现更喜欢它们的文件在某种程度上是独立的。 (例如,考虑多行字符串文字。)通常,您实际上也希望重置更多的解析器状态(行号,当然,有时是开始条件),但这是 yywrap 的责任。 . [注3]

要从套接字进行词法分析,您可能需要调用 recv来自您的 YY_INPUT执行。但出于实验目的,这里有一个简单的 YY_INPUT它只是从内存缓冲区返回数据:
/* Globals which describe the input buffer. */
const char* my_in_buffer = NULL;
const char* my_in_pointer = NULL;
const char* my_in_limit = NULL;
void my_set_buffer(const char* buffer, size_t buflen) {
my_in_buffer = my_in_pointer = buffer;
my_in_limit = my_in_buffer + buflen;
}

/* For debugging, limit the number of bytes YY_INPUT will
* return.
*/
#define MY_MAXREAD 26

/* This is technically incorrect because it returns 0
* on EOF, assuming that YY_NULL is 0.
*/
#define YY_INPUT(buf, ret, maxlen) do { \
size_t avail = my_in_limit - my_in_pointer; \
size_t toread = maxlen; \
if (toread > avail) toread = avail; \
if (toread > MY_MAXREAD) toread = MY_MAXREAD; \
*ret = toread; \
memcpy(buf, my_inpointer, toread); \
my_in_pointer += toread; \
} while (0)

笔记
  • 这并不完全正确。缓冲区状态包括一个标志,该标志指示是否可以重新填充缓冲区。如果您使用 yy_scan_bytes ,创建的缓冲区状态被标记为不可再填充。
  • 它实际上比这要复杂一些,因为 flex 扫描器有时需要向前看才能确定匹配了哪个 token ,并且在向前看期间可能会出现流结束指示。在扫描器备份到已识别 token 的末尾后,它仍然需要重新扫描前瞻字符,其中可能包含更多的 token 。为了处理这个问题,它在缓冲区状态中设置了一个标志,指示已经到达流的末尾,这会阻止 YY_INPUT。每次扫描程序到达缓冲区末尾时都不会被调用。尽管如此,最好确保您的 YY_INPUT如果在流结束返回后再次调用它,实现将继续返回流结束。
  • 再举一个具体的例子,假设你想实现某种 #include机制。 flex提供yy_push_state/yy_pop_state允许您实现包含堆栈的机制。你会调用 yy_push_state曾经include指令已被扫描,但 yy_pop_state需要调用yywrap .同样,很少有语言会允许 token 在包含的源文件中开始并继续遵循include。指示。
  • 关于c - Flex,连续扫描流(来自套接字)。我是否错过了使用 yywrap() 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23979378/

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