Lex是Lexical Analyzer Generator(取前三个字母)的缩写,是Unix环境下非常著名的工具,主要功能是生成一个词法分析器(scanner)的C源码,描述规则采用正则表达式(regular expression)。
Lex已经广泛地用于描述各种语言的词法分析器。
flex (the fast lexical analyser)意思是快速词法分析器。
Win-flex bison是flex和bison在Windows平台的一个移植版本,它支持flex(快速词法分析器)和bison(GNU解析器生成器)。
Win-flex bison的下载网址: https://sourceforge.net/projects/winflexbison/
点击“Download”按钮,开始下载文件“win_flex_bison-latest.zip”,文件大小仅有692KB。
解压到自己喜欢的位置。
你可以在命令行直接使用win_flex和win_bison,或者在Visual Studio中借助CustomBuildRules使用它们(详见 https://sourceforge.net/p/winflexbison/wiki/Visual%20Studio%20custom%20build%20rules/ )
flex/bison文件的例子可参看网页 https://sourceforge.net/projects/winflexbison/files/
在命令行输入 win_flex --help ,可以获得相关用法:
Usage: win_flex [OPTIONS] [FILE]...
Generates programs that perform pattern-matching on text.
Table Compression:
-Ca, --align trade off larger tables for better memory alignment
-Ce, --ecs construct equivalence classes
-Cf do not compress tables; use -f representation
-CF do not compress tables; use -F representation
-Cm, --meta-ecs construct meta-equivalence classes
-Cr, --read use read() instead of stdio for scanner input
-f, --full generate fast, large scanner. Same as -Cfr
-F, --fast use alternate table representation. Same as -CFr
-Cem default compression (same as --ecs --meta-ecs)
Debugging:
-d, --debug enable debug mode in scanner
-b, --backup write backing-up information to lex.backup
-p, --perf-report write performance report to stderr
-s, --nodefault suppress default rule to ECHO unmatched text
-T, --trace win_flex should run in trace mode
-w, --nowarn do not generate warnings
-v, --verbose write summary of scanner statistics to stdout
--hex use hexadecimal numbers instead of octal in debug outputs
Files:
-o, --outfile=FILE specify output filename
-S, --skel=FILE specify skeleton file
-t, --stdout write scanner on stdout instead of lex.yy.c
--yyclass=NAME name of C++ class
--header-file=FILE create a C header file in addition to the scanner
--tables-file[=FILE] write tables to FILE
Scanner behavior:
-7, --7bit generate 7-bit scanner
-8, --8bit generate 8-bit scanner
-B, --batch generate batch scanner (opposite of -I)
-i, --case-insensitive ignore case in patterns
-l, --lex-compat maximal compatibility with original lex
-X, --posix-compat maximal compatibility with POSIX lex
-I, --interactive generate interactive scanner (opposite of -B)
--yylineno track line count in yylineno
Generated code:
-+, --c++ generate C++ scanner class
-Dmacro[=defn] #define macro defn (default defn is '1')
-L, --noline suppress #line directives in scanner
-P, --prefix=STRING use STRING as prefix instead of "yy"
-R, --reentrant generate a reentrant C scanner
--bison-bridge scanner for bison pure parser.
--bison-locations include yylloc support.
--stdinit initialize yyin/yyout to stdin/stdout
--nounistd do not include
--wincompat windows compatibility (uses
--noFUNCTION do not generate a particular FUNCTION
Miscellaneous:
-c do-nothing POSIX option
-n do-nothing POSIX option
-?
-h, --help produce this help message
-V, --version report win_flex version
参考网页 https://www.cnblogs.com/zhuyingchun/p/9129366.html 中的例子。
(1)创建文本文件“a.l”(即编写lex程序)
使用文本编辑器创建文件“d:/temp/a.l”,内容如下:
%{
int num_lines = 0, num_chars = 0;
%}
%%
++num_lines; ++num_chars;
. ++num_chars;
%%
int main()
{
yyin = fopen("d:/temp/a.l","r");
yylex();
fclose(yyin);
printf("lines = %d, chars = %d ", num_lines, num_chars);
}
int yywrap()
{
return 1;
}
双百分号“%%”,是lex编译器的专用字符串,用于区分lex程序文件中的声明部分、转换规则(每个规则由模式和动作两部分组成,模式即正则表达式,动作即程序代码)、辅助过程(即C语言编写的函数)。
(2)使用win_flex编译文件“a.l”
在命令行窗口输入命令(wincompat参数,命令lex编译器创建Windows兼容的程序),:
D:\Programs\win_flex_bison-latest\win_flex.exe --wincompat --outfile=d:/temp/a.yy.c d:/temp/a.l
正常执行后,生成文件“d:/temp/a.yy.c”,这个文件较大,内容较多。
(3)使用C语言编译器编译a.yy.c
我使用的C语言编译器是Visual Studio 2022。进入VS2022的开发者命令行窗口,进入目录“d: emp”执行如下编译命令: cl a.yy.c
命令执行成功后,在目录中生成文件“a.yy.exe”和“a.yy.obj”.
关于进入VS2022的开发者命令行窗口的方法,可参看网页 https://www.toutiao.com/article/7063452501693481511/?log_from=394c061792cc1_1660021719133 的相关部分。
(4)运行程序文件“a.yy.exe”
在命令行窗口运行命令“a.yy”,结果如下图所示:
该程序的运行结果是,对文件中的行数和字符数进行计数。
参考网页 https://blog.csdn.net/grandpa_pit/article/details/117195547 中的例子。
(1)创建文本文件“a.l”(即编写lex程序)
使用文本编辑器创建文件“d:/temp/b.l”,内容如下:
%{
#include
#include
int count = 0;
%}
delim [" " \r]
whitespace {delim}+
operator \+|-|\*|\/|:=|>=|<=|#|=|<<|>>|\+\+
reservedWord int|include|main|return|using|if|namespace
delimiter [,\.;\(\)\"\<\>\{\}]
constant ([0-9])+
identfier [A-Za-z]([A-Za-z]|[0-9])*
%%
{reservedWord} {count++;printf("%d (rw,%s) ",count,yytext);}
\"[^\"]*\" {count++;printf("%d (ct,%s) ",count,yytext);}
{operator} { count++;printf("%d (op,%s) ",count,yytext); }
{delimiter} {count++;printf("%d (de,%s) ",count,yytext);}
{constant} {count++;printf("%d (ct,%s) ",count,yytext);}
{identfier} {count++;printf("%d (id,%s) ",count,yytext);}
{whitespace} { /* do nothing*/ }
%%
int main()
{
yyin = fopen("d:/temp/input.txt","r");
yylex();
fclose(yyin);
}
int yywrap()
{
return 1;
}
上述程序中使用的“d:/temp/input.txt”文件内容
#include
using namespace std;
int main(){