flex词法解析

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

%{
#include <string.h>
int chars = 0;
int lines = 0;
int words = 0;
%}

%%
[a-zA-Z]+       { chars += strlen(yytext); words++; }
\n              { lines++; }
.               { chars++; }

%%

int main(int argc, char** argv)
{
    yylex();
    printf("chars=%d,words=%d,lines=%d\n",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\n",yytext);}
\n        { printf("Enter Match=%s\n",yytext);}
[0-9]+    { printf("Digitals Match=%s\n",yytext); }
[ \t]*    { printf("SPACE Match=%s\n",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); }
\n        { lines++; chars++;}
.         { chars++ ;}

%%

main(int argc,char ** argv)
{
    int i;

    if(argc<2)
    {
        yylex();
        printf("%8d%8d%8d\n",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\n",lines,words,chars);
        totchars += chars; chars = 0;
        totwords += words; words = 0;
        totlines += lines; lines = 0;

    }

    if( argc>1 )
        printf("%8d%8d%8d total\n",totlines,totwords,totchars);
    return 0;

}

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

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

\n匹配换行

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

 

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

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

%option noyywrap

%%
"+"     { printf("PLUS\n"); }
"-"     { printf("SUBS\n"); }
"*"     { printf("MULT\n"); }
"/"     { printf("DIVDE\n"); }

[0-9]+  { printf("NUMBER %s\n",yytext); }
[ \t ]  {}  
\n      { printf("NEWLINE\n"); }

.       { printf("Mystery character %s\n",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
posted @ 2014-06-27 11:16  小郭学路  阅读(1068)  评论(0编辑  收藏  举报