1. 例子1git
功能:从标准输入读取一行,分析出其中包含的数字个数和字母个数。函数
/* filename: input.lex */ %{ int digitCount = 0; int letterCount = 0; %} digit [0-9] letter [a-zA-Z] newline \n %% {digit} digitCount++; {letter} letterCount++; {newline} return 0; %% int yywrap() { return 1;} /* main */ int main() { yylex(); printf("Numbers: %d, Letters: %d\n", digitCount, letterCount); return 0; }
测试运行:
#flex input.lex #gcc lex.yy.c #./a.out 123abc456defgh Numbers: 6, Letters: 8 #
说明:理解yylex()函数的做用,其用于进行扫描,每次调用yylex()都是从上一次扫描结束的地方开始。对于这里,只调用了一次,因此就是从标准输入的第一个字符开始扫描。那么,其什么时候返回呢?遇到return或者文件结束才会返回,因此这里须要newline时候return 0,不然,程序无法结束。
2. 例子2测试
实际的编译器工做的流程,通常来讲扫描器扫描到匹配的token都须要返回,通过一些处理,而后继续扫描,并且通常的编译器的输入都是文件。下面实现一个相似的例子,以文件做为输入,固然,这里不修改输出,通常输出都会结合其余接口去使用,好比yacc。flex
/* filename: input.lex */ %{ int digitCount = 0; int letterCount = 0; #define TOKENDIGIT 1 #define TOKENLETTER 2 %} digit [0-9] letter [a-zA-Z] newline \n %% {digit} digitCount++;return TOKENDIGIT; {letter} letterCount++;return TOKENLETTER; /*{newline} return 0;*/ %% int yywrap() { return 1;} void setInputfile(const char* filename) { FILE* fp = fopen(filename, "r"); if (filename == NULL || fp == NULL) { printf("Cannot open source file\n"); exit(0); } yyin = fp; } /* main */ int main(int argc, char* argv[]) { if (argc != 2) { printf("Only and must accept 1 auguments\n"); exit(0); } setInputfile(argv[1]); int token = yylex(); while(token != 0) { printf("Token type: %d, token: %s, token length: %d\n", token, yytext, yyleng); token = yylex(); // get next token } printf("Numbers: %d, Letters: %d\n", digitCount, letterCount); return 0; }
测试运行:
#flex input.lex #gcc lex.yy.c #cat test.txt 1ab 2d 3f #./a.out test.txt Token type: 1, token: 1, token length: 1 Token type: 2, token: a, token length: 1 Token type: 2, token: b, token length: 1 Token type: 1, token: 2, token length: 1 Token type: 2, token: d, token length: 1 Token type: 1, token: 3, token length: 1 Token type: 2, token: f, token length: 1 Numbers: 3, Letters: 4 #PS:若是读到文件尾,那么yylex()返回值为0,因此这里是while(token != 0)