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