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)