Heim  >  Artikel  >  Betrieb und Instandhaltung  >  Was ist Linux Flex?

Was ist Linux Flex?

青灯夜游
青灯夜游Original
2022-03-03 16:27:513292Durchsuche

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.

Was ist Linux Flex?

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

  • Beim Ausführen von Flex in der Befehlszeile ist der zweite Befehlszeilenparameter (hier hide-digits.l) die für Flex bereitgestellte Wortsegmentierungsmusterdatei. Diese Musterdatei enthält hauptsächlich reguläre Benutzerregeln Die Wortsegmentierung Das im Ausdruck geschriebene passende Muster wird mit Flex in die Funktion yylex im C-Codeformat übersetzt und in die Datei lex.yy.c ausgegeben. Diese Funktion kann als endlicher Automat betrachtet werden.

    Beim Ausführen von Flex in der Befehlszeile ist der zweite Befehlszeilenparameter (hier hide-digits.l) die für Flex bereitgestellte Wortsegmentierungsmusterdatei. Diese Musterdatei enthält hauptsächlich die vom Benutzer mithilfe regulärer Ausdrücke geschriebenen Wörter. Übersetzen Sie diese regulären Ausdrücke mithilfe von Flex in die Funktion yylex im C-Code-Format und geben Sie sie in die Datei lex.yy.c aus. Diese Funktion kann als endlicher Automat betrachtet werden.
  • 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.

  • flex übersetzt diesen Absatz in eine Funktion namens yylex. Die Funktion dieser Funktion besteht darin, die Eingabedatei zu scannen (standardmäßig Standardeingabe), wenn ein regulärer Ausdruck einer Regel mit einer Zeichenfolge übereinstimmt. Diese Funktion führt den C-Code aus, der der Regel folgt. Wenn in diesen C-Codes keine Return-Anweisung vorhanden ist, wird die yylex-Funktion nach der Ausführung dieser C-Codes weiter ausgeführt und startet die nächste Runde des Scannens und Abgleichens.

    Wenn das Muster mehrerer Regeln übereinstimmt, wählt yylex die Regel mit der längsten Übereinstimmungslänge aus. Wenn es Regeln mit gleicher Übereinstimmungslänge gibt, wird die Regel mit dem ersten Rang ausgewählt.
  • 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.

  • Beispiel
  • word-spliter.l
  • %%
    [0-9]+  printf("?");
    #       return 0;
    .       ECHO;
    %%

    In diesem Beispiel werden zwei von Flex bereitgestellte globale Variablen yytext und yyleng verwendet, um die gerade übereinstimmende Zeichenfolge und ihre Länge von
  • darzustellen

    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 &#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;
    }

    上面这个文件中,需要注意的是,正则表达式中,用双引号括起来的字符串就是原始字符串,里面的特殊字符是不需要转义的,而双引号本身必须转义(必须用 \” 或 \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 $<

    Was ist Linux 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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn