在linux中,flex是一個詞法分析工具,能夠識別文本中的詞法模式;Flex讀入給定的輸入文件,如果沒有給定文件名的話,則從標準輸入讀取,從而獲得一個關于需要生成的掃描器的描述。
本教程操作環(huán)境:linux5.9.8系統(tǒng)、Dell G3電腦。
flex:詞法分析器
flex是一個詞法分析器。用來將一個.l文件生成一個.c程序文件。即生成一個詞法分析器。然后讀取輸入,和正則表達式匹配,再執(zhí)行相應的動作,實現(xiàn)了程序的功能。我們可以發(fā)現(xiàn)flex實現(xiàn)在程序外部就可以接受輸入的功能。
Flex是一個生成掃描器的工具,能夠識別文本中的詞法模式。Flex 讀入給定的輸入文件,如果沒有給定文件名的話,則從標準輸入讀取,從而獲得一個關于需要生成的掃描器的描述。此描述叫做規(guī)則,由正則表達式和 C代碼對組成。Flex 的輸出是一個 C 代碼文件——lex.yy.c——其中定義了yylex() 函數(shù)。編譯輸出文件可以生成一個可執(zhí)行文件。當運行可執(zhí)行文件的時候,它分析輸入文件,為每一個正則表達式尋找匹配。當發(fā)現(xiàn)一個匹配時,它執(zhí)行與此正則表達式相關的C代碼。Flex 不是gnu工程,但是GNU為Flex 寫了手冊。
用法
-
安裝 flex
sudo?apt-get?install?flex //或者下載相應版本的安裝文件安裝
-
然后新建一個文本文件,輸入以下內容:
%% [0-9]+??printf("?"); #???????return?0; .???????ECHO; %% int?main(int?argc,?char*?argv[])?{ ????yylex(); ????return?0; } int?yywrap()?{? ????return?1; }
將此文件另存為 hide-digits.l 。注意此文件中的 %% 必須在本行的最前面(即 %% 前面不能有任何空格)。
-
之后,在終端輸入:
flex?hide-digits.l
-
此時目錄下多了一個 “l(fā)ex.yy.c” 文件,把這個 C 文件編譯并運行一遍:
?gcc?-o?hide-digits?lex.yy.c ./hide-digits
然后在終端不停的敲入任意鍵并回車,可以發(fā)現(xiàn),敲入的內容中,除數(shù)字外的字符都被原樣的輸出了,而每串數(shù)字字符都被替換成 ? 了。最后敲入 # 后程序退出了。如下:
eruiewdkfj eruiewdkfj 1245 ? fdsaf4578 fdsaf? ... #
-
當在命令行中運行 flex 時,第二個命令行參數(shù)(此處是 hide-digits.l )是提供給 flex 的分詞模式文件, 此模式文件中主要是用戶用正則表達式寫的分詞匹配模式,用flex 會將這些正則表達式翻譯成 C 代碼格式的函數(shù) yylex ,并輸出到 lex.yy.c 文件中,該函數(shù)可以看成一個有限狀態(tài)自動機。
-
當在命令行中運行 flex 時,第二個命令行參數(shù)(此處是 hide-digits.l )是提供給 flex 的分詞模式文件, 此模式文件中主要是用戶用正則表達式寫的分詞匹配模式,用flex 會將這些正則表達式翻譯成 C 代碼格式的函數(shù) yylex ,并輸出到 lex.yy.c 文件中,該函數(shù)可以看成一個有限狀態(tài)自動機。
-
下面再來詳細解釋一下 hide-digits.l 文件中的代碼,首先第一段是:
%% [0-9]+??printf("?"); #???????return?0; .???????ECHO; %%
-
flex 模式文件中,用%% 和 %%做分割, 上面分割的內容被稱為 規(guī)則(rules),本文件中每一行都是一條規(guī)則,每條規(guī)則由 匹配模式(pattern) 和 事件(action) 組成, 模式在前面,用正則表達式表示,事件在后面,即 C 代碼。每當一個模式被匹配到時,后面的 C 代碼被執(zhí)行。
-
flex 會將本段內容翻譯成一個名為 yylex 的函數(shù),該函數(shù)的作用就是掃描輸入文件(默認情況下為標準輸入),當掃描到一個完整的、最長的、可以和某條規(guī)則的正則表達式所匹配的字符串時,該函數(shù)會執(zhí)行此規(guī)則后面的 C 代碼。如果這些 C 代碼中沒有 return 語句,則執(zhí)行完這些 C 代碼后, yylex 函數(shù)會繼續(xù)運行,開始下一輪的掃描和匹配。
-
當有多條規(guī)則的模式被匹配到時, yylex 會選擇匹配長度最長的那條規(guī)則,如果有匹配長度相等的規(guī)則,則選擇排在最前面的規(guī)則。
int?main(int?argc,?char?*argv[])?{ ????yylex(); ????return?0; } int?yywrap()?{?return?1;?}
-
第二段中的 main 函數(shù)是程序的入口, flex 會將這些代碼原樣的復制到 lex.yy.c 文件的最后面。最后一行的 yywrap 函數(shù), flex 要求有這么一個函數(shù)。
示例
word-spliter.l
%{ #define?T_WORD?1 int?numChars?=?0,?numWords?=?0,?numLines?=?0; %} WORD([^?tnra]+) %% n{?numLines++;?numChars++;?} {WORD}{?numWords++;?numChars?+=?yyleng;?return?T_WORD;?} >{?return?0;?} .{?numChars++;?} %% int?main()?{ int?Token_type; while?(token_type?=?yylex())?{ printf("WORD:t%sn",?yytext); } printf("nCharstWordstLinesn"); printf("%dt%dt%dn",?numChars,?numWords,?numLines); return?0; } int?yywrap()?{ return?1; }
本例中使用到了 flex 提供的兩個全局變量 yytext 和 yyleng,分別用來表示剛剛匹配到的字符串以及它的長度
編譯執(zhí)行
flex?word-spliter.l gcc?-o?word-spliter?lex.yy.c ./word-spliter?<p>可見此程序其實就是一個原始的分詞器,它將輸入文件分割成一個個的 WORD 再輸出到終端,同時統(tǒng)計輸入文件中的字符數(shù)、單詞數(shù)和行數(shù)。此處的 WORD 指一串連續(xù)的非空格字符。</p><p><strong>擴展</strong></p><p>(1) 列出所需的所有類型的 token;</p><p>(2) 為每種類型的 token 分配一個唯一的編號,同時寫出此 token 的正則表達式;</p><p>(3) 寫出每種 token 的 rule (相應的 pattern 和 action )。</p><p>第 1 類為單字符運算符,一共 15 種:</p><pre class="brush:js;toolbar:false">+?*?-?/?%?=?,?;?!??(?)?{?}
第 2 類為雙字符運算符和關鍵字,一共 16 種:
=,?==,?!=,?&&,?|| void,?int,?while,?if,?else,?return,?break,?continue,?print,?readint
第 3 類為整數(shù)常量、字符串常量和標識符(變量名和函數(shù)名),一共 3 種。
拓展后
%{ #include?"token.h" int?cur_line_num?=?1; void?init_scanner(); void?lex_error(char*?msg,?int?line); %} /*?Definitions,?note:? 色偷偷88欧美精品久久久| 久久亚洲AV成人无码| 亚洲国产精品无码成人片久久| 国产成人综合久久精品尤物| 色噜噜狠狠先锋影音久久| 久久久久亚洲AV成人片| 亚洲AV无码一区东京热久久 | 久久无码AV一区二区三区| 日韩久久无码免费毛片软件| 久久嫩草影院免费看夜色| 亚洲国产日韩欧美综合久久| 亚洲äv永久无码精品天堂久久 | 久久精品国产亚洲AV无码麻豆| 久久精品人人做人人爽97| 久久久久久午夜成人影院| 久久w5ww成w人免费| yellow中文字幕久久网| 91久久九九无码成人网站| 亚洲欧洲久久av| 麻豆成人久久精品二区三区免费| 精品熟女少妇av免费久久| 国产精品久久久久久久午夜片 | 久久久久人妻一区二区三区vr| 久久婷婷五月综合国产尤物app| 天天综合久久久网| 性做久久久久久免费观看| 久久亚洲国产成人精品性色| 久久人妻少妇嫩草AV蜜桃| 亚洲精品乱码久久久久久蜜桃图片 | 青青热久久国产久精品| 日韩人妻无码精品久久免费一| 俺来也俺去啦久久综合网| 日韩久久久久中文字幕人妻| 97超级碰碰碰久久久久| 一级做a爰片久久毛片毛片| 久久99热精品| 精品国产乱码久久久久久人妻| 久久九九青青国产精品| 久久精品国产99久久久古代| 韩国三级中文字幕hd久久精品 | 久久精品女人天堂AV麻|