flex基本语法(2)

2020-02-23  本文已影响0人  Minority

0. 引言

1. start condition

flex为有条件地激活规则提供了一种机制。 只有当扫描器处于名为“sc”的开始条件时,其模式前缀为“<sc>”的任何规则才会处于激活状态。 例如:

<STRING>[^"]*        { /* eat up the string body ... */
            ...
            }

< >中可以为任意字符。比如上面的STRING,只有当扫描器处于“STRING”开始状态时,规则[^"]才会激活。

那么,如何退出这种规则呢?开始条件本身使用BEGIN激活。退出时使用BEGIN(0)BEGIN(0)返回到没有启动条件的规则处于活动状态的原始状态。 这个状态也可以被称为开始条件INITIAL,所以BEGIN(INITIAL)等同于BEGIN(0)

为了说明启动条件的用法,下面是一个扫描器,它提供了两种不同的字符串解释,例如“123.456”。 默认情况下,它会将它视为三个标识(token),整数“123”,点('。')和整数“456”。 但是如果字符串在字符串“expect-floats”的前面出现,它会将其视为单个标记,即浮点数123.456:

%{
#include <math.h>
%}
%s expect

%%
expect-floats        BEGIN(expect);   //如果出现expect-floats ,进行expect的规则匹配

<expect>[0-9]+"."[0-9]+      {
                    printf( "found a float, = %f\n\n",
                    atof( yytext ) );
              }
<expect>\n     {

            BEGIN(INITIAL);    //如果匹配到换行符,退出整个expect匹配
            }


// 下面的匹配规则不在BEGIN(expect); 之列,还和之前一样正常匹配。出现expect-floats时才触发BEGIN
[0-9]+      {

            printf( "found an integer, = %d\n",
                    atoi( yytext ) );
            }

"."         printf( "found a dot\n" );

%%

int main(int argc, char* argv[]) {
    yylex();
    return 0;
}
int yywrap() { 
    return 1;
}

运行结果:

2. yymore()

告诉扫描程序下次匹配规则时,应将相应的令牌附加到yytext的当前值上,而不是替换它。

%%
    mega-    ECHO; yymore();
    kludge   ECHO;

例如,上面的程序。如果没有yymore的情况下,在输入为“ mega-kludge”时,会输出“mega-kludge”,在有yymore()的情况下,mega-匹配打印完还在缓存区存着一份mega-。在kludge 匹配成功后,缓冲区的mega-随着kludge 一起打印,所以将输出以下内容“ mega-mega-kludge”:

3. yyless()

yyless(n)将当前token的除前n个字符外的所有字符返回给输入流,在此位置,当扫描程序寻找下一个匹配项时,将重新扫描它们。 yytext和yyleng已适当调整(例如yyleng现在等于n)。

%%
    foobar    ECHO; yyless(3);
    [a-z]+    ECHO;

例如,在输入“ foobar”上,以下内容将写出“ foobarbar”。相当于yyless(3)会将foobar的后三个(除前3个外)字符再进行一次匹配。

4. 综合应用——匹配字符串

code:

%%
\"[^\"\n]*\"                      {
                                    if(yytext[yyleng-2]=='\\') /* 检查这个引号是不是转义字符 */
                                    {
                                      yyless(yyleng-1);       /* 如果是转义字符需要退回进行重新匹配 */
                                      yymore();       /*下一次被匹配的字符串被添加在当前识别出的字符串后面*/
                                    }
                                    else
                                    {
                                      printf("%s\n",yytext);;
                                    }
                                  }

\"[^\"\n]*$                     {printf("Line %3d: Unterminated string %s\n",yylineno,yytext);} 
                                 /*此处\n不能省;帮忙判断一次输入结束*/
.                               ECHO;
%%

int main(int argc, char* argv[]) {
    yylex();
    return 0;
}

int yywrap() {
    return 1;
}

结果:

这种是考虑的比较周到的;像中间有转义的引号的情况都能处理;"hello\"world"这样的字符串都能处理。



本文参考:https://zhuanlan.zhihu.com/p/65490271
更详细的flex使用方法:https://zhuanlan.zhihu.com/p/108167693

上一篇下一篇

猜你喜欢

热点阅读