• flex词法解析


    例子1、从标准输入的字数、单词、行数统计

    %{
    #include <string.h>
    int chars = 0;
    int lines = 0;
    int words = 0;
    %}
    
    %%
    [a-zA-Z]+       { chars += strlen(yytext); words++; }
    
                  { lines++; }
    .               { chars++; }
    
    %%
    
    int main(int argc, char** argv)
    {
        yylex();
        printf("chars=%d,words=%d,lines=%d
    ",chars,words,lines);
    
        return 0;
    }
    

     对应的Makefile文件:

    test:wc.l
            flex wc.l
            gcc -W -o test lex.yy.c
    clean:
            rm -rf test lex.yy.o
    

     出现错误信息:

    [root@typhoeus79 flex]# make
    flex wc.l
    gcc -W -o test lex.yy.c
    /tmp/ccSylYmr.o: In function `yylex':
    lex.yy.c:(.text+0x413): undefined reference to `yywrap'
    /tmp/ccSylYmr.o: In function `input':
    lex.yy.c:(.text+0xcb8): undefined reference to `yywrap'
    collect2: ld returned 1 exit status
    make: *** [test] Error 1
    

    解决方案1:添加设置noyywrap设置 ,

    %option noyywrap
    

    解决方案2:设置绑定flex对应的库:

    gcc -W -o test lex.yy.c -lfl
    

      

    例子2、从一个文件中读取分析的内容,按照字母组成、数字、空格以及换行符进行区分

    [root@typhoeus79 wc]# more test.l 
    /*默认是从标准输入输出读取,设置该选项支持从文件读取*/
    %option noyywrap
    %{
    %}
    
    %%
    
    [a-zA-Z]+ { printf("CHAR Match=%s
    ",yytext);}
    
            { printf("Enter Match=%s
    ",yytext);}
    [0-9]+    { printf("Digitals Match=%s
    ",yytext); }
    [ 	]*    { printf("SPACE Match=%s
    ",yytext); }
    
    %%
    
    main(int argc,char ** argv)
    {
        int i;
    
        if(argc<2)
        {
            yylex();
            return 0;
        }
    
        for(i=1; i < argc; i++)
        {
            FILE *f = fopen(argv[i],"r");
    
            if(!f){
                perror(argv[i]);
                return (1);
            }
    
            //yyrestart使词法分析器从f中读取标准输入文件
            yyrestart(f);
            yylex();
            fclose(f);
    
        }
    
        return 0;
    
    }
    

    测试:

    [root@typhoeus79 wc]# more Makefile 
    test:lex.yy.c
            flex test.l
            gcc -W -o test lex.yy.c
    [root@typhoeus79 wc]# 
    [root@typhoeus79 wc]# make
    flex test.l
    gcc -W -o test lex.yy.c
    [root@typhoeus79 wc]# more tmp 
    aaaee   AAQQZZ
    CCDD 1234
    56
    [root@typhoeus79 wc]# ./test tmp 
    CHAR Match=aaaee
    SPACE Match=   
    CHAR Match=AAQQZZ
    Enter Match=
    
    CHAR Match=CCDD
    SPACE Match= 
    Digitals Match=1234
    Enter Match=
    
    Digitals Match=56
    Enter Match=
    
    [root@typhoeus79 wc]# 
    

    从输出中可以看出从文件逐个读取,按照模式最大匹配,并存储在yytext中。

    例子3:模拟wc的简单例子

    [root@typhoeus79 wc]# more wc.l 
    /*默认是从标准输入输出读取,设置该选项支持从文件读取*/
    %option noyywrap
    
    %{
        int chars = 0;
        int lines = 0;
        int words = 0;
    
        int totchars = 0;
        int totlines = 0;
        int totwords = 0;
    %}
    
    %%
    
    [a-zA-Z]+ { words++; chars += strlen(yytext); }
    
            { lines++; chars++;}
    .         { chars++ ;}
    
    %%
    
    main(int argc,char ** argv)
    {
        int i;
    
        if(argc<2)
        {
            yylex();
            printf("%8d%8d%8d
    ",lines,words,chars);
            return 0;
        }
    
        for(i=1; i < argc; i++)
        {
            FILE *f = fopen(argv[i],"r");
    
            if(!f){
                perror(argv[i]);
                return (1);
            }
    
            //yyrestart使词法分析器从f中读取标准输入文件
            yyrestart(f);
            yylex();
            fclose(f);
    
            printf("%8d%8d%8d
    ",lines,words,chars);
            totchars += chars; chars = 0;
            totwords += words; words = 0;
            totlines += lines; lines = 0;
    
        }
    
        if( argc>1 )
            printf("%8d%8d%8d total
    ",totlines,totwords,totchars);
        return 0;
    
    }
    

    例子中具有三种匹配规则:

    [a-zA-Z]+匹配1个或者多个字母组成的字符串

    匹配换行

    .匹配除了换行符以外的其他任意单一字符

    可以看到规则1和规则3之间可能存在冗余,例如单个字符a,两个规则都可以匹配上,优先匹配规则1,故规则的顺序影响匹配的内容

    例子4:词法分析解析算数表达式 

    %option noyywrap
    
    %%
    "+"     { printf("PLUS
    "); }
    "-"     { printf("SUBS
    "); }
    "*"     { printf("MULT
    "); }
    "/"     { printf("DIVDE
    "); }
    
    [0-9]+  { printf("NUMBER %s
    ",yytext); }
    [ 	 ]  {}  
    
          { printf("NEWLINE
    "); }
    
    .       { printf("Mystery character %s
    ",yytext); }                                                                         
    
    %%
    

     测试例子:

    [root@typhoeus79 flex]# ./test 
    5 6 / 7q
    NUMBER 5
    NUMBER 6
    DIVDE
    NUMBER 7
    Mystery character q
    NEWLINE
    12+34
    NUMBER 12
    PLUS
    NUMBER 34
    NEWLINE
  • 相关阅读:
    Silverlight 4版本升级到4.0.60531.0
    Silverlight实例教程 理解Navigation导航框架Page类
    微软官方在线培训课程汇总2011版
    分享Silverlight/WPF/Windows Phone一周学习导读(07月11日07月17日)
    Linux内核简介
    Brief Summary of IaaS, PaaS, SaaS
    On Amazon EC2's Underlying Architecture
    Linux进程管理(2)
    一个诡异的时间问题追查[转]
    查看一个进程打开了哪些文件的命令
  • 原文地址:https://www.cnblogs.com/gsblog/p/3811571.html
Copyright © 2020-2023  润新知