如何防止Flex丢弃yyinput字符?

时间:2017-01-24 10:17:43

标签: bison flex-lexer yacc lex

我试图读取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 = '\0'; /* preserve yytext */
yy_hold_char = *++yy_c_buf_p;

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

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

2 个答案:

答案 0 :(得分:0)

您正在匹配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的一部分了。)

答案 1 :(得分:0)

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

%{
    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 */

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