使用 bison 和 flex 实现一个解析字符串的函数

Implementing a function that parses a string using bison and flex

我已经使用 bison 和 flex 实现了解析器和扫描器。起初它从 stdin 读取输入,后来我修改为从字符串读取。 Whosebug 上有几篇关于此主题的帖子。具体来说,at flex manual 描述了多个缓冲区的使用以及使用内存中的字符串而不是文件作为输入有帮助。

所以,我得到了 parser/lexer 来处理单个字符串,如:

%{
//Bunch of includes, typedefs, etc..
extern char * yytext;
void yyerror(char *);
int yylex();
typedef struct yy_buffer_state * YY_BUFFER_STATE;
extern int yyparse();
extern int yylex_destroy(void);
extern YY_BUFFER_STATE yy_scan_string(char * str);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
...

%%
int main(int argc, char **argv) {

  char *string = "abcd\n[=10=]";
  YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
  yyparse();

}

这是简单的部分。 grammar/lex 规则在这里重现有点冗长。 我想实现一个将使用字符串参数重复调用的函数。由于 grammar/lex 规则可以处理输出,所以我可以处理它。问题是要有一种机制来实现一个经典函数,将字符串传递给该函数进行解析和分析。所以,我试过这个来测试...

int main(int argc, char **argv) {
  int i=10;
  char *string;
  string = malloc(16);
  while (1) {

     sprintf(string, "someString to be parsed...%d\n[=11=]", i++);
     YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));   
     yyparse();
     yylex_destroy();
     printf("%d\n", i); 

   }
}

它在大约 10000 次后失败,出现以下错误:

 fatal flex scanner internal error--end of buffer missed

我没有考虑任何多线程环境。它将是一个单线程进程,其中的字符串来自要解析的套接字。当一个字符串到达​​时,我调用一个函数来解析它。 我找不到任何关于使用 Bison 和 Flex 实现此类功能的参考资料。

我尝试了不同的方法,但没有成功。任何简单的方法来处理这个?

string = malloc(16);

有点吝啬,考虑到你要写:

sprintf(string, "someString to be parsed...%d\n[=11=]", ++i);

如果i是一个数字,则至少为28个字节,当i达到10000时,则达到32个字节。(这可能不是巧合。)

帮自己一个忙,如果可以的话使用 asprintf。如果它不可用,使用 snprintf 编写它很容易,或者您可以使用 snprintf 和更大的缓冲区。 (在这种情况下不需要动态分配。)

请注意,格式字符串末尾的 [=17=] 完全没有意义。我假设您的意图是保证有两个 NUL 终止符,正如 yy_scan_buffer 所要求的那样,但是 [=17=] 不会被复制到 sprintf 的输出中,因为它的作用是终止格式字符串。 (C 字符串以 NUL 字符结尾,记住。)

还要注意 yy_scan_buffer(string, sizeof(string)); 中的 sizeof(string)sizeof(char*),因为 stringchar*。这几天很可能是 8,但如果您使用的是 32 位环境,则可能是 4。无论如何,它与sprintf写的字符数无关。您可以使用 strlen 来计算 string 的长度,但利用 sprintf returns 它写入的字节数这一事实会更有效。

说到 return 值,您没有检查 yy_scan_buffer 中的 return 值,这可能是想告诉您您的错误:

If you fail to set up base in this manner (i.e., forget the final two YY_END_OF_BUFFER_CHAR bytes), then yy_scan_buffer() returns a NULL pointer instead of creating a new input buffer.

我不知道这是否是你需要的,但无论如何这是我在 Bison 中写的

int calc(char str[]) 
{
    YY_BUFFER_STATE buffer = yy_scan_string(str);
    yyparse();
    yy_delete_buffer(buffer);
    return 0;
}