我有一个程序用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的长度是多少?可以重新定义吗?
答案 0 :(得分:2)
除非您在flex输入文件中明确设置%array
选项(这不是一个好主意[1]),yytext
没有固定大小。通常,它只是包含令牌的输入缓冲区的一部分,这就是为什么在需要保留令牌的字符串表示之前,必须复制yytext
才能再次调用词法分析器的原因。 (我怀疑你的问题是不这样做的结果。)
由于flex通常以固定长度的片段读取输入,因此令牌可能跨越两个或更多个缓冲区。在这种情况下,flex需要将令牌的第一部分复制到缓冲区的开头[2],可能使缓冲区变大realloc
,然后从输入读取以填充缓冲区的其余部分。 flex逻辑的这一部分没有经过优化,因为它相对不频繁;特别是,在继续使用下一个输入字符之前,会重新扫描整个当前令牌,如果您有大型令牌和小输入缓冲区,则会产生大幅减速。
正如我所说,明显缓冲区损坏的最常见原因始终是无法复制yytext
。如果您需要保留yytext
:
从yylex返回之前,
在致电unput
之前(如果您使用此功能)。
备注强>
[1]如果您指定%array
,则flex
无法扩展缓冲区,并且最大令牌大小略小于YYLMAX
。默认情况下,YYLMAX
约为8k,但它是一个宏,您可以在flex序言中重新定义它。但是,没有充分的理由来指定这个选项;它所做的就是减慢你的扫描速度并限制令牌的大小。存在与旧版lex
兼容的选项;一些旧软件对yytext
采取了一些自由,这对于flex
是不可能的。
[2]实际上,在 缓冲区的开头,因为只有一个缓冲区。缓冲区中存在的任何旧令牌都将被覆盖,这是需要复制yytext
的另一个原因。