apa itu linux flex

青灯夜游
Lepaskan: 2022-03-03 16:27:51
asal
3553 orang telah melayarinya

Dalam Linux, flex ialah alat analisis leksikal yang boleh mengenal pasti corak leksikal dalam teks, Flex membaca fail input yang diberikan, atau jika tiada nama fail diberikan, ia membaca daripada input standard, dengan itu Mendapat penerangan tentang; pengimbas yang akan dihasilkan.

apa itu linux flex

Persekitaran pengendalian tutorial ini: sistem linux5.9.8, komputer Dell G3.

flex: Penganalisis leksikal

flex ialah penganalisis leksikal. Digunakan untuk menjana fail .l ke dalam fail program .c. Iaitu, penganalisis leksikal dihasilkan. Kemudian baca input, padankannya dengan ungkapan biasa, dan kemudian lakukan tindakan yang sepadan untuk merealisasikan fungsi program. Kita boleh mendapati bahawa flex melaksanakan fungsi menerima input di luar program.

Flex ialah alat yang menjana pengimbas yang mampu mengenal pasti corak leksikal dalam teks. Flex membaca fail input yang diberikan, atau input standard jika tiada nama fail diberikan, untuk mendapatkan penerangan pengimbas yang akan dijana. Penerangan ini dipanggil peraturan dan terdiri daripada pasangan ungkapan biasa dan kod C. Output Flex ialah fail kod C—lex.yy.c—di mana fungsi yylex() ditakrifkan. Menyusun fail output menghasilkan fail boleh laku. Apabila boleh laku dijalankan, ia menganalisis fail input, mencari padanan untuk setiap ungkapan biasa. Apabila padanan ditemui, ia melaksanakan kod C yang dikaitkan dengan ungkapan biasa ini. Flex bukan projek GNU, tetapi GNU telah menulis manual untuk Flex.

Penggunaan

  • Pasang flex

sudo apt-get install flex
//或者下载相应版本的安装文件安装
Salin selepas log masuk
  • Kemudian buat fail teks baharu dan masukkan kandungan berikut:

%%
[0-9]+  printf("?");
#       return 0;
.       ECHO;
%%
int main(int argc, char* argv[]) {
    yylex();
    return 0;
}
int yywrap() { 
    return 1;
}
Salin selepas log masuk

Simpan fail ini sebagai angka sembunyi . Ambil perhatian bahawa %% dalam fail ini mestilah pada permulaan baris ini (iaitu, tidak boleh ada sebarang ruang di hadapan %%). Selepas

  • , masukkan dalam terminal:

flex hide-digits.l
Salin selepas log masuk
  • Di kali ini Terdapat fail "lex.yy.c" tambahan dalam direktori Susun dan jalankan fail C ini:

 gcc -o hide-digits lex.yy.c
./hide-digits
Salin selepas log masuk

Kemudian teruskan menaip mana-mana Tekan butang. kekunci dan tekan Enter Anda boleh mendapati bahawa dalam kandungan yang ditaip, semua aksara kecuali nombor adalah output sebagaimana adanya, dan setiap rentetan aksara angka digantikan dengan ?. Akhir sekali, taip # dan program keluar. Seperti berikut:

eruiewdkfj
eruiewdkfj
1245
?
fdsaf4578
fdsaf?
...
#
Salin selepas log masuk
  • Apabila menjalankan flex pada baris arahan, parameter baris arahan kedua (hide-digits.l di sini) ialah fail mod segmentasi perkataan yang disediakan untuk flex , ini fail corak terutamanya mengandungi corak pemadanan pembahagian perkataan yang ditulis oleh pengguna dengan ungkapan biasa Gunakan flex untuk menterjemah ungkapan biasa ini ke dalam fungsi yylex dalam format kod C, dan mengeluarkannya ke fail lex.yy.c. Fungsi ini boleh dilihat dalam sebuah automaton keadaan terhingga.

  • Apabila menjalankan flex pada baris arahan, parameter baris arahan kedua (hide-digit.l di sini) ialah fail mod segmentasi perkataan yang disediakan untuk flex Dalam fail mod ini corak pemadanan pembahagian perkataan yang ditulis oleh pengguna dengan ungkapan biasa Flex akan menterjemahkan ungkapan biasa ini ke dalam fungsi yylex dalam format kod C dan mengeluarkannya ke fail lex.yy.c. Fungsi ini boleh dianggap sebagai mesin automatik keadaan terhingga.

  • Mari jelaskan kod dalam fail hide-digits.l secara terperinci Pertama sekali, perenggan pertama ialah:

%%
[0-9]+  printf("?");
#       return 0;
.       ECHO;
%%
Salin selepas log masuk
<🎜. >
  • Dalam fail corak flex, %% dan %% digunakan untuk pemisahan Kandungan yang dibahagikan di atas dipanggil peraturan Setiap baris dalam fail ini adalah peraturan (corak) yang sepadan Ia terdiri daripada peristiwa (tindakan) Corak berada di hadapan, dinyatakan dengan ungkapan biasa, dan acara berada di belakang, iaitu kod C. Setiap kali corak dipadankan, kod C berikut dilaksanakan.

  • flex akan menterjemah perenggan ini kepada fungsi bernama yylex Fungsi fungsi ini adalah untuk mengimbas fail input (input standard secara lalai apabila lengkap, rentetan terpanjang yang boleh). sepadan dengan ungkapan biasa peraturan, fungsi ini akan melaksanakan kod C di belakang peraturan ini. Jika tiada pernyataan pemulangan dalam kod C ini, selepas melaksanakan kod C ini, fungsi yylex akan terus berjalan dan memulakan pusingan pengimbasan dan pemadanan yang seterusnya.

  • Apabila corak berbilang peraturan dipadankan, yylex akan memilih peraturan dengan panjang padanan terpanjang Jika terdapat peraturan dengan panjang padanan yang sama, ia akan dipilih di bahagian atas .

int main(int argc, char *argv[]) {
    yylex();
    return 0;
}
int yywrap() { return 1; }
Salin selepas log masuk
  • Fungsi utama dalam perenggan kedua ialah titik masuk program flex akan menyalin kod ini tidak berubah ke penghujung lex.yy .c fail mi. Fungsi yywrap dalam baris terakhir, flex memerlukan fungsi sedemikian.

Contoh

pemecah kata.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;
}
Salin selepas log masuk
Dalam contoh ini, dua pembolehubah global yytext dan yyleng yang disediakan oleh flex digunakan, masing-masing, untuk mewakili rentetan yang baru dipadankan dan panjangnya

Kompil dan laksanakan

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
Salin selepas log masuk

可见此程序其实就是一个原始的分词器,它将输入文件分割成一个个的 WORD 再输出到终端,同时统计输入文件中的字符数、单词数和行数。此处的 WORD 指一串连续的非空格字符。

扩展

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

(2) 为每种类型的 token 分配一个唯一的编号,同时写出此 token 的正则表达式;

(3) 写出每种 token 的 rule (相应的 pattern 和 action )。

第 1 类为单字符运算符,一共 15 种:

+ * - / % = , ; ! < > ( ) { }
Salin selepas log masuk

第 2 类为双字符运算符和关键字,一共 16 种:

<=, >=, ==, !=, &&, ||
void, int, while, if, else, return, break, continue, print, readint
Salin selepas log masuk

第 3 类为整数常量、字符串常量和标识符(变量名和函数名),一共 3 种。

拓展后

%{
#include "token.h"
int cur_line_num = 1;
void init_scanner();
void lex_error(char* msg, int line);
%}
/* Definitions, note: \042 is &#39;"&#39; */
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;
}
Salin selepas log masuk

上面这个文件中,需要注意的是,正则表达式中,用双引号括起来的字符串就是原始字符串,里面的特殊字符是不需要转义的,而双引号本身必须转义(必须用 \” 或 \042 ),这是 flex 中不同于常规的正则表达式的一个特性。

除单字符运算符外的 token 的编号则在下面这个 token.h 文件,该文件中同时提供了一个 print_token 函数,可以根据 token 的编号打印其名称。

#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
Salin selepas log masuk

makefile

out: scanner
scanner: lex.yy.c token.h
gcc -o $@ $<
lex.yy.c: scanner.l
flex $<
Salin selepas log masuk

apa itu linux flex

相关推荐:《Linux视频教程

Atas ialah kandungan terperinci apa itu linux flex. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan