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
浙公网安备 33010602011771号