为什么在词法分析器EOF处理动作中需要调用yyterminate()?
问题描述
我编写了一个用于统计输入行数的简易词法分析器,代码如下所示。可以看到,当触发文件结束(EOF)条件时,程序会输出统计得到的行数,对应动作中调用了yyterminate()。测试发现,如果不调用yyterminate(),输出结果会反复重复打印行数统计值,请问为什么此处必须调用yyterminate()?
实现代码如下:
%option noyywrap %option yylineno %% . { } \n { } <<EOF>> { fprintf(stdout, "%d", yylineno); yyterminate(); } %% int main() { yylex(); }
原因解答
- flex生成的
yylex()扫描器核心是一个持续运行的循环:读取输入内容、匹配对应规则、执行规则动作,直到收到明确的终止指令。<<EOF>>是flex提供的特殊匹配模式,仅代表当前输入流已经读取到末尾,匹配到该规则不会自动终止扫描循环。 - 如果
<<EOF>>的动作中没有调用yyterminate(),执行完打印行数的逻辑后,扫描器会回到循环起点,再次尝试读取输入、匹配token。此时输入流已经处于结束状态,没有任何可读取的有效字符,扫描器会立刻再次匹配到<<EOF>>规则,再次执行打印动作,之后又回到循环起点,形成无限死循环,外在表现就是反复重复打印行数统计值。 yyterminate()是flex提供的专用扫描终止接口,调用后会立刻结束yylex()的运行,直接返回到调用yylex()的上层代码(即本示例中的main函数),从根源上打断上述死循环。- 补充说明:flex内置的默认EOF处理逻辑自带终止扫描的操作,但只要用户自定义了
<<EOF>>规则,默认处理逻辑就会被完全覆盖。此时必须在自定义的EOF动作里明确指定后续行为:要么调用yyterminate()结束扫描,要么调用yyrestart()绑定新的输入流继续扫描,否则必然会出现循环匹配EOF规则的异常。
内容的提问来源于stack exchange,提问作者Roger Costello
相关产品推荐
相关产品推荐

