美文网首页
flex基本语法(2)

flex基本语法(2)

作者: Minority | 来源:发表于2020-02-23 17:08 被阅读0次

    0. 引言

    • flex的安装及基本使用点击

    • flex的正则匹配语法点击

    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;
    }
    

    运行结果:

    • 注意:开始条件没有自己的名称空间; %s和%x的声明方式与#define相同。
    • 注意:expect-floats条件满足时输出的数小数点后保留6位是c语言的特性。

    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个外)字符再进行一次匹配。

    • 注意:yyless()出现在需要进行回退处理的情况下,yyless()的参数0将导致再次扫描整个当前输入字符串。 除非您更改了扫描程序随后处理其输入的方式(例如,使用BEGIN),否则将导致无限循环。
    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

    相关文章

      网友评论

          本文标题:flex基本语法(2)

          本文链接:https://www.haomeiwen.com/subject/ssgjqhtx.html