【问题标题】:Flex - create a buffer state from a string WITHOUT setting it as the active bufferFlex - 从字符串创建缓冲区状态而不将其设置为活动缓冲区
【发布时间】:2013-11-29 16:57:34
【问题描述】:

Flex manual on Multiple Input Buffers

你可以在那里看到:

以下例程可用于设置输入缓冲区以扫描内存中的字符串而不是文件。它们都为扫描字符串创建了一个新的输入缓冲区,并返回相应的 YY_BUFFER_STATE 句柄(完成后应使用 yy_delete_buffer() 删除)。他们还使用 yy_switch_to_buffer() 切换到新缓冲区,因此下一次调用 yylex() 将开始扫描字符串。

那你有yy_scan_string之类的

通常 Flex 的默认设置很好,我有一个文件要扫描,或者只需要一个扫描仪,但是这个任务是不同的。

我正在尝试创建一个能够扫描多个文件和一些字符串的扫描仪。它是可重入的,我以前从未使用过 YY_INPUT()。

所以我的问题如下:

当一个缓冲区完成并且没有任何东西可以扫描时,Flex 是否会将该状态从堆栈中弹出,如果有另一个状态开始扫描它是如何停止的?

我的意思是它是如何停止的,就好像它在一条规则的中途。假设我尝试匹配ab,如果一个状态以a 结尾,而另一个以b 开头,那该如何处理?


问题

/** Pushes the new state onto the stack. The new state becomes
 *  the current state. This function will allocate the stack
 *  if necessary.
 *  @param new_buffer The new state.
 *  @param yyscanner The scanner object.
 */
void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
    if (new_buffer == NULL)
        return;

    yyensure_buffer_stack(yyscanner);

    /* This block is copied from yy_switch_to_buffer. */
    if ( YY_CURRENT_BUFFER )
        {
        /* Flush out information for old buffer. */
        *yyg->yy_c_buf_p = yyg->yy_hold_char;
        YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
        YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
        }

    /* Only push if top exists. Otherwise, replace top. */
    if (YY_CURRENT_BUFFER)
        yyg->yy_buffer_stack_top++;
    YY_CURRENT_BUFFER_LVALUE = new_buffer;

    /* copied from yy_switch_to_buffer. */
    yy_load_buffer_state(yyscanner );
    yyg->yy_did_buffer_switch_on_eof = 1;
}

按 null 不起作用

旧物

我的期望

我希望 yylex 返回 0 意味着缓冲区结束(并让我有机会操纵它们)

我还希望除非我重新启动扫描仪,否则它将继续从上次停止的地方继续(因此如果一个缓冲区以 a 结尾而另一个缓冲区以 b 开头,则 ab 将匹配,除非我明确地重新启动扫描仪)

其次,如何在不将 flex 设置为活动缓冲区的情况下准备字符串缓冲区。

我想我可以创建一个新的“空”缓冲区(请参阅链接中的创建缓冲区函数)推送它,然后将它推送到堆栈上。

当我从字符串创建缓冲区时,我希望该函数设置输入缓冲区,这是输入堆栈的顶部,它将无害地删除我的“空”缓冲区。

对于原本如此可爱的东西来说,这似乎很混乱。

询问原因

对此进行测试将非常困难。我还必须假设我知道 flex 是如何正确工作的,然后根据我认为它如何工作来设计通过或失败的测试,看看它是否真的有效。这需要很长时间,即使结果是错误的,我也可能无法获得支持我的模型的结果。

【问题讨论】:

    标签: c bison flex-lexer


    【解决方案1】:

    标记不能跨越缓冲区边界——单个标记的所有字符必须来自同一个缓冲区。最容易将缓冲区视为保存一系列字符,后跟一个 EOF —— flex 将通过从当前缓冲区读取字符来匹配一个标记,如果没有匹配的标记,将匹配默认的“匹配任何单个字符作为标记并回应它”的规则。您的令牌操作代码可能会切换缓冲区,在这种情况下,下一个令牌将来自新缓冲区。缓冲区永远不会在令牌中间切换,也永远不会“自动”切换——您需要在代码中的某处显式切换。

    当 flex 到达缓冲区的末尾(除了 EOF 标记之外没有剩余字符),它将匹配 <<EOF>> 规则(可能会切换到新缓冲区),或者调用 yywrap(你可以想到yywrap 作为“默认”<<EOF>> 规则)。默认的yywrap 不会更改缓冲区并导致yylex 返回一个0 标记。由于缓冲区没有改变,如果你在不改变缓冲区的情况下再次调用yylex,它会再次做同样的事情。

    yy_scan_string/bytes 切换到新缓冲区的事实是您通过保存当前缓冲区并恢复来解决的烦恼:

    YY_BUFFER_STATE cur = YY_CURRENT_BUFFER;
    YY_BUFFER_STATE n = yy_scan_string(str);
    yy_switch_to_buffer(cur);
    

    通常会紧跟yypush_buffer_state(n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-09
      相关资源
      最近更新 更多