Flex:使用 yymore()

Lor*_*rin 1 c++ g++ flex-lexer

这是 .lex 文件的片段:

    /* Empty line just with the newline character signs end of
       the title block 
     */
<title>^[\n]{1} {
    yymore(); ECHO;
    // std::cout << "Text: " << yytext << std::endl;

    // ... do something with yytext

    BEGIN(INITIAL);

}

    /* Reads everything up to the end of line. */
<title>.+ {
    ECHO; yymore();
    //std::cout << "yymore: " << yytext << std::endl;
}

    /* Every title starts with # and text follows. */
#[\t\ ] {

    // ... prepare for html output

    BEGIN(title);
}
Run Code Online (Sandbox Code Playgroud)

目标是阅读“#”之后的全文。根据在线教程,yymore()应该将当前 yytext 的内容附加到最后一个。在部分中使用ECHO; yymore();组合<title>.+显示整个文本。然而,删除 ECHO 并使用cout会导致yymore()损坏。未附加文本。

此外,我无法获取<title>^[\n]{1}部分中的标题文本。我得到的一切都只是“\n”。

我做错了什么?

ric*_*ici 5

这并不是对 的准确描述yymoreyymore将导致下一个标记yytext包含当前的yytext. (之前的文本已经消失了;它无法恢复——当然,除非它被标记为通过调用来保存yymore())。

我不明白你期望这个开始条件做什么。

据称终止启动条件的模式是:

<title>^[\n]{1}
Run Code Online (Sandbox Code Playgroud)

^定模式,因此它仅在换行符之后匹配。(它是一个零长度谓词,就像在标准 Posix 正则表达式中一样。)但是起始条件中的模式不可能title满足^匹配,因为在该状态下匹配的任何模式都不能匹配以换行符结尾的字符串(.不匹配换行符,并且#[\t ]规则显然以空格或制表符结尾。)

另外,{1}是完全多余的(它意味着“恰好一次重复”,这是一种恒等变换)并且[\n]与 没有什么不同\n,所以你可以直接写:

<title>^\n
Run Code Online (Sandbox Code Playgroud)

我的猜测是您没有指定%option nodefault,因此您让默认匹配默默地回显而不显示错误消息。问题在于,yymore()由于显而易见的原因,标准默认匹配规则不会调用 ,因此在执行默认操作时,累积的匹配会丢失。

还要注意ECHO回声yytext;如果您使用yymore(或yyless),那么这与“此规则匹配的文本块”不同。考虑以下简单的弹性程序:

%option noyywrap noinput nounput nodefault
%%
.    { yymore(); ECHO; putchar('\n'); }
\n
Run Code Online (Sandbox Code Playgroud)

示例运行:

$ flex -o tri.c tri.l
$ gcc -Wall -o tri tri.c -lfl
$ ./tri <<<0123456789
0
01
012
0123
01234
012345
0123456
01234567
012345678
0123456789
Run Code Online (Sandbox Code Playgroud)