久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

linux的中怎么安裝和使用flex

共計(jì) 5344 個(gè)字符,預(yù)計(jì)需要花費(fèi) 14 分鐘才能閱讀完成。

這篇“l(fā)inux 的中怎么安裝和使用 flex”文章的知識(shí)點(diǎn)大部分人都不太理解,所以丸趣 TV 小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“l(fā)inux 的中怎么安裝和使用 flex”文章吧。

在 linux 中,flex 是一個(gè)詞法分析工具,能夠識(shí)別文本中的詞法模式;Flex 讀入給定的輸入文件,如果沒(méi)有給定文件名的話,則從標(biāo)準(zhǔn)輸入讀取,從而獲得一個(gè)關(guān)于需要生成的掃描器的描述。

本教程操作環(huán)境:linux5.9.8 系統(tǒng)、Dell G3 電腦。

flex: 詞法分析器

flex 是一個(gè)詞法分析器。用來(lái)將一個(gè).l 文件生成一個(gè).c 程序文件。即生成一個(gè)詞法分析器。然后讀取輸入,和正則表達(dá)式匹配,再執(zhí)行相應(yīng)的動(dòng)作,實(shí)現(xiàn)了程序的功能。我們可以發(fā)現(xiàn) flex 實(shí)現(xiàn)在程序外部就可以接受輸入的功能。

Flex 是一個(gè)生成掃描器的工具,能夠識(shí)別文本中的詞法模式。Flex 讀入給定的輸入文件,如果沒(méi)有給定文件名的話,則從標(biāo)準(zhǔn)輸入讀取,從而獲得一個(gè)關(guān)于需要生成的掃描器的描述。此描述叫做規(guī)則,由正則表達(dá)式和 C 代碼對(duì)組成。Flex 的輸出是一個(gè) C 代碼文件——lex.yy.c——其中定義了 yylex() 函數(shù)。編譯輸出文件可以生成一個(gè)可執(zhí)行文件。當(dāng)運(yùn)行可執(zhí)行文件的時(shí)候,它分析輸入文件,為每一個(gè)正則表達(dá)式尋找匹配。當(dāng)發(fā)現(xiàn)一個(gè)匹配時(shí),它執(zhí)行與此正則表達(dá)式相關(guān)的 C 代碼。Flex 不是 GNU 工程,但是 GNU 為 Flex 寫(xiě)了手冊(cè)。

用法

安裝 flex

sudo apt-get install flex
// 或者下載相應(yīng)版本的安裝文件安裝 

然后新建一個(gè)文本文件,輸入以下內(nèi)容:

%%
[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

此時(shí)目錄下多了一個(gè)“l(fā)ex.yy.c”文件,把這個(gè) C 文件編譯并運(yùn)行一遍:

 gcc -o hide-digits lex.yy.c
./hide-digits

然后在終端不停的敲入任意鍵并回車,可以發(fā)現(xiàn),敲入的內(nèi)容中,除數(shù)字外的字符都被原樣的輸出了,而每串?dāng)?shù)字字符都被替換成 ? 了。最后敲入 # 后程序退出了。如下:

eruiewdkfj
eruiewdkfj
fdsaf4578
fdsaf?
#

當(dāng)在命令行中運(yùn)行 flex 時(shí),第二個(gè)命令行參數(shù)(此處是 hide-digits.l)是提供給 flex 的分詞模式文件,此模式文件中主要是用戶用正則表達(dá)式寫(xiě)的分詞匹配模式,用 flex 會(huì)將這些正則表達(dá)式翻譯成 C 代碼格式的函數(shù) yylex,并輸出到 lex.yy.c 文件中,該函數(shù)可以看成一個(gè)有限狀態(tài)自動(dòng)機(jī)。

當(dāng)在命令行中運(yùn)行 flex 時(shí),第二個(gè)命令行參數(shù)(此處是 hide-digits.l)是提供給 flex 的分詞模式文件,此模式文件中主要是用戶用正則表達(dá)式寫(xiě)的分詞匹配模式,用 flex 會(huì)將這些正則表達(dá)式翻譯成 C 代碼格式的函數(shù) yylex,并輸出到 lex.yy.c 文件中,該函數(shù)可以看成一個(gè)有限狀態(tài)自動(dòng)機(jī)。

下面再來(lái)詳細(xì)解釋一下 hide-digits.l 文件中的代碼,首先第一段是:

%%
[0-9]+ printf( ? 
# return 0;
. ECHO;
%%

flex 模式文件中,用 %% 和 %% 做分割,上面分割的內(nèi)容被稱為 規(guī)則(rules),本文件中每一行都是一條規(guī)則,每條規(guī)則由 匹配模式(pattern)和 事件(action)組成,模式在前面,用正則表達(dá)式表示,事件在后面,即 C 代碼。每當(dāng)一個(gè)模式被匹配到時(shí),后面的 C 代碼被執(zhí)行。

flex 會(huì)將本段內(nèi)容翻譯成一個(gè)名為 yylex 的函數(shù),該函數(shù)的作用就是掃描輸入文件(默認(rèn)情況下為標(biāo)準(zhǔn)輸入),當(dāng)掃描到一個(gè)完整的、最長(zhǎng)的、可以和某條規(guī)則的正則表達(dá)式所匹配的字符串時(shí),該函數(shù)會(huì)執(zhí)行此規(guī)則后面的 C 代碼。如果這些 C 代碼中沒(méi)有 return 語(yǔ)句,則執(zhí)行完這些 C 代碼后,yylex 函數(shù)會(huì)繼續(xù)運(yùn)行,開(kāi)始下一輪的掃描和匹配。

當(dāng)有多條規(guī)則的模式被匹配到時(shí),yylex 會(huì)選擇匹配長(zhǎng)度最長(zhǎng)的那條規(guī)則,如果有匹配長(zhǎng)度相等的規(guī)則,則選擇排在最前面的規(guī)則。

int main(int argc, char *argv[]) { yylex();
 return 0;
int yywrap() { return 1; }

第二段中的 main 函數(shù)是程序的入口,flex 會(huì)將這些代碼原樣的復(fù)制到 lex.yy.c 文件的最后面。最后一行的 yywrap 函數(shù),flex 要求有這么一個(gè)函數(shù)。

示例

word-spliter.l

%{
#define T_WORD 1
int numChars = 0, numWords = 0, numLines = 0;
WORD([^ \t\n\r\a]+)
\n{ numLines++; numChars++; }
{WORD}{ numWords++; numChars += yyleng; return T_WORD; }
 EOF { return 0; }
.{ numChars++; }
int main() {
int token_type;
while (token_type = yylex()) {printf( WORD:\t%s\n , yytext);
printf( \nChars\tWords\tLines\n 
printf(%d\t%d\t%d\n , numChars, numWords, numLines);
return 0;
int yywrap() {return 1;}

本例中使用到了 flex 提供的兩個(gè)全局變量 yytext 和 yyleng,分別用來(lái)表示剛剛匹配到的字符串以及它的長(zhǎng)度

編譯執(zhí)行

flex word-spliter.l
gcc -o word-spliter lex.yy.c
./word-spliter   word-spliter.l
WORD: %{
WORD: #define
WORD: }
Chars Words Lines
470 70 27

可見(jiàn)此程序其實(shí)就是一個(gè)原始的分詞器,它將輸入文件分割成一個(gè)個(gè)的 WORD 再輸出到終端,同時(shí)統(tǒng)計(jì)輸入文件中的字符數(shù)、單詞數(shù)和行數(shù)。此處的 WORD 指一串連續(xù)的非空格字符。

擴(kuò)展

(1)列出所需的所有類型的 token;

(2)為每種類型的 token 分配一個(gè)唯一的編號(hào),同時(shí)寫(xiě)出此 token 的正則表達(dá)式;

(3)寫(xiě)出每種 token 的 rule(相應(yīng)的 pattern 和 action)。

第 1 類為單字符運(yùn)算符,一共 15 種:

+ * - / % = , ; !     ( ) { }

第 2 類為雙字符運(yùn)算符和關(guān)鍵字,一共 16 種:

=,  =, ==, !=,  , ||
void, int, while, if, else, return, break, continue, print, readint

第 3 類為整數(shù)常量、字符串常量和標(biāo)識(shí)符(變量名和函數(shù)名),一共 3 種。

拓展后

%{
#include  token.h 
int cur_line_num = 1;
void init_scanner();
void lex_error(char* msg, int line);
/* Definitions, note: \042 is   */
INTEGER ([0-9]+)
UNTERM_STRING (\042[^\042\n]*)
STRING (\042[^\042\n]*\042)
IDENTIFIER ([_a-zA-Z][_a-zA-Z0-9]*)
OPERATOR ([+*-/%=,;! (){}])
SINGLE_COMMENT1 (// [^\n]*)
SINGLE_COMMENT2 (# [^\n]*)
[\n] { cur_line_num++; }
[ \t\r\a]+ { /* ignore all spaces */ }
{SINGLE_COMMENT1} { /* skip for single line comment */ }
{SINGLE_COMMENT2} { /* skip for single line commnet */ }
{OPERATOR} { return yytext[0]; } 
 =  { return T_Le; }
 =  { return T_Ge; }
 ==  { return T_Eq; }
 !=  { return T_Ne; }
  { return T_And; }
 ||  { return T_Or; }
 void  { return T_Void; }
 int  { return T_Int; }
 while  { return T_While; }
 if  { return T_If; }
 else  { return T_Else; }
 return  { return T_Return; }
 break  { return T_Break; }
 continue  { return T_Continue; }
 print  { return T_Print; }
 readint  { return T_ReadInt; }
{INTEGER} { return T_IntConstant; }
{STRING} { return T_StringConstant; }
{IDENTIFIER} { return T_Identifier; }
 EOF  { return 0; }
{UNTERM_STRING} { lex_error( Unterminated string constant , cur_line_num); }
. { lex_error( Unrecognized character , cur_line_num); }
int main(int argc, char* argv[]) {
 int token;
 init_scanner();
 while (token = yylex()) { print_token(token);
 puts(yytext);
 }
 return 0;
void init_scanner() {
 printf( %-20s%s\n ,  TOKEN-TYPE ,  TOKEN-VALUE 
 printf( -------------------------------------------------\n 
void lex_error(char* msg, int line) { printf( \nError at line %-3d: %s\n\n , line, msg);
int yywrap(void) { return 1;}

上面這個(gè)文件中,需要注意的是,正則表達(dá)式中,用雙引號(hào)括起來(lái)的字符串就是原始字符串,里面的特殊字符是不需要轉(zhuǎn)義的,而雙引號(hào)本身必須轉(zhuǎn)義(必須用 \”或 \042),這是 flex 中不同于常規(guī)的正則表達(dá)式的一個(gè)特性。

除單字符運(yùn)算符外的 token 的編號(hào)則在下面這個(gè) token.h 文件,該文件中同時(shí)提供了一個(gè) print_token 函數(shù),可以根據(jù) token 的編號(hào)打印其名稱。

#ifndef TOKEN_H
#define TOKEN_H
typedef enum {
 T_Le = 256, T_Ge, T_Eq, T_Ne, T_And, T_Or, T_IntConstant,
 T_StringConstant, T_Identifier, T_Void, T_Int, T_While,
 T_If, T_Else, T_Return, T_Break, T_Continue, T_Print,
 T_ReadInt
} TokenType;
static void print_token(int token) { static char* token_strs[] = {
  T_Le ,  T_Ge ,  T_Eq ,  T_Ne ,  T_And ,  T_Or ,  T_IntConstant ,
  T_StringConstant ,  T_Identifier ,  T_Void ,  T_Int ,  T_While ,
  T_If ,  T_Else ,  T_Return ,  T_Break ,  T_Continue ,  T_Print ,
  T_ReadInt 
 };
 if (token   256) { printf( %-20c , token);
 } else { printf( %-20s , token_strs[token-256]);
 }
#endif

makefile

out: scanner
scanner: lex.yy.c token.h
gcc -o $@ $ 
lex.yy.c: scanner.l
flex $

以上就是關(guān)于“l(fā)inux 的中怎么安裝和使用 flex”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望丸趣 TV 小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注丸趣 TV 行業(yè)資訊頻道。

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-03發(fā)表,共計(jì)5344字。
轉(zhuǎn)載說(shuō)明:除特殊說(shuō)明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒(méi)有評(píng)論)
主站蜘蛛池模板: 安顺市| 龙海市| 玉树县| 陵川县| 六安市| 峨山| 佛学| 新龙县| 安塞县| 耿马| 鄂州市| 莱州市| 涞源县| 达州市| 遂昌县| 石屏县| 鄄城县| 桑日县| 都昌县| 遵义县| 噶尔县| 邯郸市| 宁安市| 茶陵县| 榆社县| 肇源县| 文安县| 平江县| 庐江县| 汤原县| 肃南| 万山特区| 彰化县| 龙山县| 晋州市| 贞丰县| 新竹县| 贡觉县| 沙洋县| 姚安县| 临朐县|