我正在使用flex lexer。有没有办法(1)让输入字符串(2)中的当前索引在未来的时间点跳回到该索引?
感谢。
答案 0 :(得分:2)
维持当前输入位置相当容易。匹配任何规则时,yyleng
包含匹配的长度,因此将yyleng
添加到已处理的累积长度就足够了。假设您正在使用flex,则不必将代码直接插入到每个规则操作中,这将是乏味的。相反,您可以使用YY_USER_ACTION
宏:
#define YY_USER_ACTION input_pos += yyleng;
(这假设您已在某处定义了input_pos
,并安排在词汇扫描开始时将其初始化为0.)
如果您使用REJECT
,yymore()
,yyless()
或input()
,这将导致错误的结果;在所有这些情况下,您必须调整input_pos
的值。对于yymore()
的每次通话,您需要从yyleng
中减去input_pos
;这也适用于REJECT
。对于yyless()
的来电,您可以在通话前减去yyleng
,并在通话后将其重新添加。对于input()
的每次通话,您需要向input_pos
添加一个。
在规则中,您可以使用input_pos
作为匹配 end 的位置,或input_pos - yyleng
作为匹配开头的位置。< / p>
返回保存位置比较棘手。
(F)lex不会将整个输入保留在内存中,因此原则上您需要使用fseek()
将yyin
倒回到正确的位置。但是,在二进制模式下尚未打开yyin
的常见情况下,您无法可靠地使用fseek()
返回计算输入偏移量。因此,至少,您必须确保以二进制模式打开(或重新打开)yyin
。
此外,通常不能保证所附加的任何流yyin
都可以重绕(它可能是控制台输入,管道或其他一些不可搜索的设备)。因此,为了完全通用,您可能必须使用临时文件来存储从流中读取的数据。当您尝试重新读取先前的输入时,这将产生额外的复杂性,因为您必须切换到临时文件以进行读取,直到完成为止,此时您将不得不返回到主文件。 yywrap
的广告使用将简化此过程。
请注意,在回放输入流后 - 无论是否切换到从临时文件中读取 - 都必须调用yyrestart()
来重置扫描仪的输入缓冲区。 (这也是一个仅限flex的功能; Posix lex没有指定通知扫描仪需要重置其缓冲区的机制,因此如果您不使用flex,则必须查阅扫描仪生成器的相关文档。)