lex yacc yytext令牌大小

时间:2014-04-30 15:42:04

标签: c yacc lex

我有一个程序用LEX和YACC处理一些句子。我最初是在一个带有lex 2.5.35和bison(GNU bison)2.5的Debian盒子里开发的。我已将代码迁移到CentOS服务器,我有lex 2.5.35和bison(GNU Bison)2.4.1。在开发服务器中,一切都运行良好

当我收到长令牌(超过1000个字符)时,我看到一些奇怪的行为。每个char数组都已定义足够长以支持这个但我看到当yytext获取这个长字符串时其他数组被改变(我想到缓冲区溢出)。

这是否有意义或者我误解了什么?

yytext的长度是多少?可以重新定义吗?

1 个答案:

答案 0 :(得分:2)

除非您在flex输入文件中明确设置%array选项(这不是一个好主意[1]),yytext没有固定大小。通常,它只是包含令牌的输入缓冲区的一部分,这就是为什么在需要保留令牌的字符串表示之前,必须复制yytext才能再次调用词法分析器的原因。 (我怀疑你的问题是不这样做的结果。)

由于flex通常以固定长度的片段读取输入,因此令牌可能跨越两个或更多个缓冲区。在这种情况下,flex需要将令牌的第一部分复制到缓冲区的开头[2],可能使缓冲区变大realloc,然后从输入读取以填充缓冲区的其余部分。 flex逻辑的这一部分没有经过优化,因为它相对不频繁;特别是,在继续使用下一个输入字符之前,会重新扫描整个当前令牌,如果您有大型令牌和小输入缓冲区,则会产生大幅减速。

正如我所说,明显缓冲区损坏的最常见原因始终是无法复制yytext。如果您需要保留yytext

的值,则必须执行此操作
  1. 从yylex返回之前,

  2. 在致电unput之前(如果您使用此功能)。


  3. 备注

    [1]如果您指定%array,则flex无法扩展缓冲区,并且最大令牌大小略小于YYLMAX。默认情况下,YYLMAX约为8k,但它是一个宏,您可以在flex序言中重新定义它。但是,没有充分的理由来指定这个选项;它所做的就是减慢你的扫描速度并限制令牌的大小。存在与旧版lex兼容的选项;一些旧软件对yytext采取了一些自由,这对于flex是不可能的。

    [2]实际上,在 缓冲区的开头,因为只有一个缓冲区。缓冲区中存在的任何旧令牌都将被覆盖,这是需要复制yytext的另一个原因。