In Linux ist Flex ein lexikalisches Analysetool, das lexikalische Muster in Texten identifizieren kann. Wenn kein Dateiname angegeben ist, liest es aus der Standardeingabe, um Informationen darüber zu erhalten, was benötigt wird der generierte Scanner.
Die Betriebsumgebung dieses Tutorials: Linux5.9.8-System, Dell G3-Computer.
flex: Lexikalischer Analysator
flex ist ein lexikalischer Analysator. Wird verwendet, um eine .l-Datei in eine .c-Programmdatei zu generieren. Das heißt, es wird ein lexikalischer Analysator generiert. Lesen Sie dann die Eingabe, vergleichen Sie sie mit dem regulären Ausdruck und führen Sie dann die entsprechende Aktion aus, um die Funktion des Programms zu realisieren. Wir können feststellen, dass Flex die Funktion implementiert, Eingaben außerhalb des Programms zu akzeptieren.
Flex ist ein Tool, das Scanner generiert, die lexikalische Muster in Texten identifizieren können. Flex liest die angegebene Eingabedatei oder die Standardeingabe, wenn kein Dateiname angegeben ist, um eine Beschreibung des zu generierenden Scanners zu erhalten. Diese Beschreibung wird als Regel bezeichnet und besteht aus Paaren regulärer Ausdrücke und C-Code. Die Ausgabe von Flex ist eine C-Codedatei – lex.yy.c –, in der die Funktion yylex() definiert ist. Durch das Kompilieren der Ausgabedatei wird eine ausführbare Datei erstellt. Wenn die ausführbare Datei ausgeführt wird, analysiert sie die Eingabedatei und sucht nach einer Übereinstimmung für jeden regulären Ausdruck. Wenn eine Übereinstimmung gefunden wird, wird der diesem regulären Ausdruck zugeordnete C-Code ausgeführt. Flex ist kein GNU-Projekt, aber GNU hat ein Handbuch für Flex geschrieben. Installieren Sie Flex hide-digits.l. Beachten Sie, dass %% in dieser Datei am Anfang dieser Zeile stehen muss (d. h. vor %%) dürfen keine Leerzeichen stehen.
Danach geben Sie im Terminal ein:
sudo apt-get install flex //或者下载相应版本的安装文件安装
Zu diesem Zeitpunkt befindet sich eine zusätzliche Datei „lex.yy.c“ im Verzeichnis. Kompilieren Sie diese C-Datei und führen Sie sie aus:
%% [0-9]+ printf("?"); # return 0; . ECHO; %% int main(int argc, char* argv[]) { yylex(); return 0; } int yywrap() { return 1; }
Dann geben Sie weiterhin eine beliebige Taste im Terminal ein und drücken Sie die Eingabetaste. Sie können feststellen, dass im eingegebenen Inhalt alle Zeichen außer Zahlen so ausgegeben werden, wie sie sind, und jede Folge numerischer Zeichen durch ? ersetzt wird. Geben Sie abschließend # ein und das Programm wird beendet. Wie folgt: flex hide-digits.l
Lassen Sie uns den Code in der Datei hide-digits.l im Detail erklären. Der erste Absatz lautet zunächst:
gcc -o hide-digits lex.yy.c ./hide-digits
Flex-Modus-Datei, verwenden Sie %% und %%, um den Inhalt aufzuteilen Von den oben genannten Split-Regeln ist jede Zeile in dieser Datei eine Regel. Jede Regel besteht aus einem passenden Muster und einem Ereignis. Das Muster befindet sich im Vordergrund, dargestellt durch einen regulären Ausdruck, und das Ereignis befindet sich im Hintergrund C-Code. Immer wenn ein Muster übereinstimmt, wird der folgende C-Code ausgeführt.
eruiewdkfj eruiewdkfj 1245 ? fdsaf4578 fdsaf? ... #
Die Hauptfunktion im zweiten Absatz ist der Einstiegspunkt des Programms. Flex kopiert diese Codes unverändert an das Ende der Datei lex.yy.c. Die yywrap-Funktion in der letzten Zeile, Flex erfordert eine solche Funktion.
%% [0-9]+ printf("?"); # return 0; . ECHO; %%
Zusammenstellung und Ausführung
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
可见此程序其实就是一个原始的分词器,它将输入文件分割成一个个的 WORD 再输出到终端,同时统计输入文件中的字符数、单词数和行数。此处的 WORD 指一串连续的非空格字符。
扩展
(1) 列出所需的所有类型的 token;
(2) 为每种类型的 token 分配一个唯一的编号,同时写出此 token 的正则表达式;
(3) 写出每种 token 的 rule (相应的 pattern 和 action )。
第 1 类为单字符运算符,一共 15 种:
+ * - / % = , ; ! < > ( ) { }
第 2 类为双字符运算符和关键字,一共 16 种:
<=, >=, ==, !=, &&, || void, int, while, if, else, return, break, continue, print, readint
第 3 类为整数常量、字符串常量和标识符(变量名和函数名),一共 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; }
上面这个文件中,需要注意的是,正则表达式中,用双引号括起来的字符串就是原始字符串,里面的特殊字符是不需要转义的,而双引号本身必须转义(必须用 \” 或 \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
makefile
out: scanner scanner: lex.yy.c token.h gcc -o $@ $< lex.yy.c: scanner.l flex $<
相关推荐:《Linux视频教程》
Das obige ist der detaillierte Inhalt vonWas ist Linux Flex?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!