如何防止 Flex 丢弃 yyinput 字符?

How can I prevent Flex from discarding yyinput characters?

我正在尝试读取 Flex 词法分析器中已知数量(在运行时)的字符。我知道它以 CRLF 开头,所以我匹配它,然后使用 yyinput.

读取 literal_length 个字符
<EXPECT_LITERAL>"\r\n"      {
    for(int i=0;i<literal_length;i++){
        int c= yyinput(yyg);
        if(c == EOF) break;
    }
    *yylval = val_new_s(yytext);
    return(LITERAL);
}

但是yyinput并没有添加新字符,而是包含:

*yy_c_buf_p = '[=11=]'; /* preserve yytext */
yy_hold_char = *++yy_c_buf_p;

这意味着 yytext 没有获得额外的 literal_length 个字符。如果可以避免的话,我宁愿不创建一个新的缓冲区来存储它们,因为我知道字符序列已经在内存中了。

除了完全重新定义yyinput(),有没有办法保留yytext中多余的字符?

您正在匹配 CRLF,因此 yytext 包含 CRLF。

如果要匹配CRLF后面的数字,则需要匹配数字:

%x EXPECT_DIGITS

<EXPECT_LITERAL>\r\n    BEGIN(EXPECT_DIGITS); /* ignore otherwise */
<EXPECT_DIGITS>[0-9]*   BEGIN(INITIAL);       /* parse yytext here */ return LITERAL;

字符可能已被读取是您不能依赖的实现细节。

您可能可以将匹配稍微简化一点,以便在没有特殊状态的情况下摆脱困境(例如,您可以匹配 \r\n[0-9]*,那么数字已经是 yytext 的一部分了)。

您可以在单独的状态下匹配数字,当您拥有所有数字时终止状态:

%{
    uint64_t accumulator;
    unsigned int remaining_digits;
%}

%x EXPECT_DIGITS

<EXPECT_LITERAL>\r\n    BEGIN(EXPECT_DIGITS); remaining_digits = literal_length; accumulator = 0;
<EXPECT_DIGITS>[0-9]    accumulator = accumulator * 10 + *yytext - '0'; if(!--remaining_digits) { BEGIN(INITIAL); *yylval = accumulator; return LITERAL; }
<EXPECT_DIGITS>.        /* handle non-digits */

显然,这需要更多的错误处理。