Befehl "lex"

Zweck

Generiert ein Programm in der Programmiersprache C oder C++, das Muster für eine einfache lexikalische Analyse eines Eingabedatenstroms abgleicht.

Syntax

Lex [ -C ] [ -t. ] [ -v| -n ] [ Datei... ]

Beschreibung

Der Befehl lex eine angegebene Datei oder die Standardeingabe, erzeugt ein Programm in der Programmiersprache C und schreibt diese in eine Datei mit dem Namen lex.yy.c. Diese Datei, lex.yy.c, ist ein kompilierbares Programm in der Programmiersprache C. Die Ausgabe des Befehls lex knn auch mit einem C++-Compiler kompiliert werden. Das Flag -C benennt die Ausgabedatei für den C++-Compiler in lex.yy.C um.

Das vom Befehl lex generierte C++-Programm kann entweder STDIO oder IOSTREAMS verwenden. Wenn die cpp define _CPP_IOSTREAMS während einer C + + -Kompilierung wahr ist, verwendet das Programm IOSTREAMS für alle Ein-/Ausgaben. Andernfalls wird STDIO verwendet.

Der Befehl lex verwendet Regeln und Aktionen, die in der angegebenen Datei enthalten sind, um ein Programm, lex.yy.c, zu generieren, das mit dem Befehl cc kompiliert werden kann. Die kompilierte Datei lex.yy.c kann dann Eingaben empfangen, die Eingabe in die logischen Teile aufteilen, die durch die Regeln in der angegebenen Datei definiert werden, und Programmfragmente ausführen, die in den Aktionen in der angegebenen Datei enthalten sind.

Das generierte Programm ist eine Funktion der Programmiersprache C mit dem Namen yylex. Der Befehl lex speichert die Funktion yylex in einer Datei mit dem Namen lex.yy.c. Sie können die Funktion yylex allein verwenden, um einfache, aus einem Wort bestehende Eingaben zu erkennen, oder Sie können die Funktion zusammen mit anderen Programmen der Programmiersprache C verwenden, um komplexere Eingabeanalysefunktionen auszuführen. Mit dem Befehl lex können Sie beispielsweise ein Programm generieren, das einen Eingabedatenstrom vereinfacht, bevor er an ein vom Befehl yacc generiertes Parserprogramm gesendet wird.

Die Funktion yylex analysiert den Eingabedatenstrom unter Verwendung einer Programmstruktur, die als finite Zustandsmaschine bezeichnet wird. Diese Struktur ermöglicht dem Programm, jeweils nur in einem einzigen Zustand zu existieren. Es ist eine endliche (finite) Anzahl von Zuständen zulässig. Die Regeln in der angegebenen Datei bestimmen, wie das Programm von einem Zustand in einen anderen wechselt.

Wenn Sie keine Datei angeben, liest der Befehl lex die Standardeingabe. Der Befehl behandelt mehrere Dateien als eine einzige Datei.

Anmerkung: Da der Befehl lex feste Namen für Zwischen- und Ausgabedateien verwendet, kann von lex nur ein einziges Programm in einem bestimmten Verzeichnis generiert werden.

lex-Spezifikationsdatei

Die Eingabedatei kann drei Abschnitte enthalten: Definitionen, Regeln und Benutzersubroutinen. Jeder Abschnitt muss von den anderen durch eine Zeile getrennt werden, die nur den Begrenzer enthält.%%(doppelte Prozentzeichen). Das Format ist folgendes:

Der Zweck und das Format jedes Abschnitts sind im Folgenden beschrieben.

Definitionen

Wenn Sie Variablen in Ihren Regeln verwenden möchten, müssen Sie sie in diesem Abschnitt definieren. Die Variablen bilden die linke Spalte und ihre Definitionen die rechte Spalte. Wenn Sie beispielsweiseDAls numerische Ziffer würden Sie Folgendes schreiben:

D   [0-9]

Sie können eine definierte Variable im Regelabschnitt verwenden, indem Sie den Variablennamen in{}(braces), for example:

{D}

Zeilen im Definitionsabschnitt, die mit einem Leerzeichen beginnen oder eingeschlossen sind in%{, %}Begrenzungszeilen werden in die Datei lex.yy.c kopiert. Sie können dieses Konstrukt verwenden, um Variablen in der Programmiersprache C zu deklarieren, die in den lex-Aktionen oder für den Einschluss von Headerdateien verwendet werden sollen, z. B.:

%{
#include <math.h>
int count;
%}

Solche Zeilen können auch am Beginn des Regelabschnitts unmittelbar nach dem ersten%%Begrenzer, aber sie sollten nirgendwo anders im Regelabschnitt verwendet werden. Wenn sich die Zeile im Definitionsabschnitt der angegebenen Datei befindet, kopiert der Befehl lex sie in den Abschnitt mit den externen Deklarationen der Datei lex.yy.c. Wenn die Zeile im Regelabschnitt vor der ersten Regel erscheint, kopiert der Befehl lex sie in den Abschnitt mit den lokalen Deklarationen der Subroutine yylex in lex.yy.c. Solche Zeilen sollten nicht hinter der ersten Regel vorkommen.

Der Typ des externen lex , yytext, kann entweder auf ein auf null endende Zeichenarray (Standardwert) gesetzt werden oder auf einen Zeiger auf eine auf null endende Zeichenfolge, indem eine der folgenden Angaben im Definitionsabschnitt angegeben wird:

%array    (default)
%pointer

Im Definitionsabschnitt können Sie Tabellengrößen für die generierte finite Zustandsmaschine festlegen. Die Standardgrößen sind für kleine Programme groß genug. Für komplexere Programme können Sie aber auch größere Größen festlegen.

Element Beschreibung
%an Die Anzahl der Übergänge ist n (Standardwert 5000).
%en Die Anzahl der Syntaxanalysebaumknoten ist n (Standardwert 2000).
%hn Die Anzahl der Ausgabebereiche für Mehrbytezeichen (Standardwert 0).
%kn Die Anzahl gepackter Zeichenklassen (Standardwert 1000).
%mn Die Anzahl der Ausgabebereiche für Zeichen aus Mehrbytezeichenklassen (Standardwert 0).
%nn Die Anzahl der Zustände ist n (Standardwert 2500).
%on Die Anzahl der Ausgabebereiche (Standardwert 5000, mindestens 257).
%pn Die Anzahl der Positionen ist n (Standardwert 5000).
%vp Prozentsatz der freien Slots in den Hashtabellen, die von %h und %m gesteuert werden (Standardwert: 20, Bereich 0 < = P < 100).
%zn Die Anzahl der Ausgabebereiche für Mehrbytezeichenklassen (Standardwert 0).

Wenn Mehrbytezeichen in Zeichenfolgen erweiterter regulärer Ausdrücke erscheinen, müssen Sie die Größe des Ausgabearrays möglicherweise mit dem Argument %o zurücksetzen (unter Umständen auf Array-Größen zwischen 10.000 und 20.000). Diese Zurücksetzung spiegelt die sehr viel größere Anzahl von Zeichen relativ zur Anzahl der Einzelbytezeichen wider.

Wenn Mehrbytezeichen in erweiterten regulären Ausdrücken vorkommen, müssen Sie die Größen der Mehrbyte-Hashtabellen mit den Argumenten %h und %m auf Größen setzen, die größer sind als die Gesamtzahl der in der lex-Datei enthaltenen Mehrbytezeichen.

Wenn in erweiterten regulären Ausdrücken keine Mehrbytezeichen vorhanden sind, Sie jedoch '.' Damit Mehrbytezeichen übereinstimmen, müssen Sie %z auf einen Wert größer als null setzen. Damit Inverszeichenklassen (z. B. [^abc]) als Entsprechung für Mehrbytezeichen verwendet werden können, müssen Sie %h und %m auf einen Wert größer als null setzen.

Wenn Mehrbytezeichen verwendet werden, muss die Datei lex.yy.c mit der Compileroption -qmbcs kompiliert werden.

Regeln

Sobald Sie Ihre Bedingungen definiert haben, können Sie den Regelabschnitt schreiben. Dieser Abschnitt enthält Zeichenfolgen und Ausdrücke, die von der Subroutine yylex abgeglichen werden sollen, und C-Befehle, die ausgeführt werden sollen, wenn eine Übereinstimmung gefunden wird. Dieser Abschnitt ist erforderlich und ihm muss ein Begrenzer vorangestellt werden.%%(doppelte Prozentzeichen), unabhängig davon, ob Sie einen Definitionsabschnitt haben. Der Befehl lex erkennt Ihre Regeln ohne diesen Begrenzer nicht.

In diesem Abschnitt enthält die linke Spalte das Muster in Form eines erweiterten regulären Ausdrucks, das in einer Eingabedatei der Subroutine yylex erkannt wird. Die rechte Spalte enthält das C-Programmfragment, das ausgeführt wird, wenn dieses Muster erkannt wird, und als Aktion bezeichnet wird.

Wenn das Programm für lexikalische Analyse eine Übereinstimmung für den erweiterten regulären Ausdruck findet, führt es die Aktion aus, die diesem erweiterten regulären Ausdruck zugeordnet ist.

Muster können erweiterte Zeichen enthalten. Wenn Ländereinstellungen für Mehrbytesprachen auf Ihrem System installiert sind, können Muster auch Mehrbytezeichen enthalten, die Teil des installierten codierten Zeichensatzes sind.

Die Spalten sind durch ein Tabulator- oder Leerzeichen getrennt. Wenn Sie beispielsweise Dateien nach dem Schlüsselwort KEY durchsuchen möchten, können Sie Folgendes schreiben:

(KEY) printf ("found KEY");

Wenn Sie diese Regel in die angegebene Datei einfügen, sucht das Programm für lexikalische Analyse yylex das Muster KEY und führt die Subroutine printf aus.

Jedes Muster kann eine entsprechende Aktion haben, d. h. einen C-Befehl, der ausgeführt werden soll, wenn das Muster gefunden wird. Jede Anweisung muss mit einem;(Semikolon). Wenn Sie mehr als eine Anweisung in einer Aktion verwenden, müssen Sie alle Anweisungen in{ }(geschweifte Klammern). Ein zweiter Begrenzer,%%muss den Regelabschnitt befolgen, wenn Sie über einen Abschnitt Benutzersubroutine verfügen. Wenn keine Aktion für eine Musterübereinstimmung angegeben ist, kopiert das Programm für lexikalische Analyse das Eingabemuster in die Ausgabe, ohne es zu ändern.

Wenn das Programm für lexikalische Analyse yylex eine übereinstimmende Zeichenfolge im Eingabedatenstrom findet, kopiert es die übereinstimmende Zeichenfolge in ein externes Zeichenarray (oder einen Zeiger auf eine Zeichenfolge) yytext, bevor es Befehle im Regelabschnitt ausführt. In ähnlicher Weise wird die externe Integervariable yyleng auf die Länge der übereinstimmenden Zeichenfolge in Bytes gesetzt (daher haben Mehrbytezeichen eine Größe größer als 1).

Benutzersubroutinen

Die lex-Bibliothek definiert die folgenden Subroutinen als Makros, die Sie im Regelabschnitt der lex-Spezifikationsdatei verwenden können:

Element Beschreibung
input Liest ein Byte aus yyin.
unput Ersetzt ein Byte, nachdem es gelesen wurde.
output Schreibt ein Ausgabebyte in yyout.
Winput Liest einen Mehrbytezeichen aus yyin.
wunput Ersetzt ein Mehrbytezeichen, nachdem es gelesen wurde.
wAusgabe Schreibt ein Mehrbyteausgabezeichen in yyout.
jjsetlocale Ruft die Subroutine setlocale (LC_ALL, " " ); auf, um die aktuelle Ländereinstellung zu bestimmen.

Die Makros winput, wunput und woutput sind für die Verwendung der Subroutinen yywinput, yywunput und yywoutput definiert, die in der Datei lex.yy.c codiert sind. Aus Gründen der Kompatibilität verwenden diese yy-Subroutinen anschließend die Subroutinen input, unput und output, um die erforderliche Anzahl von Bytes in einem vollständigen Mehrbytezeichen zu lesen, zu ersetzen und zu schreiben.

Sie können diese Makros überschreiben, indem Sie Ihren eigenen Code für diese Routinen im Abschnitt mit den Benutzerroutinen schreiben. Wenn Sie jedoch eigene Makros schreiben, müssen Sie die Definition dieser Makros im Definitionsabschnitt wie folgt aufheben:

%{
#undef input
#undef unput
#undef output
#undef winput
#undef wunput
#undef woutput
#undef yysetlocale
%}

Es gibt keine Subroutine main in lex.yy.c, weil die lex-Bibliothek die Subroutine main enthält, die das Programm für lexikalische Analyse yylex aufruft, sowie die Subroutine yywrap, die von yylex( ) am Ende der angegebenen Datei aufgerufen wird. Wenn Sie also main ()und/oder yywrap ()nicht in den Abschnitt für Benutzersubroutinen einschließen, müssen Sie Folgendes eingeben: lex.yy.ccclex.yy.c-ll, wobeillruft die lex -Bibliothek auf.

Vom Befehl lex generierte externe Namen beginnen alle mit dem Präfix yy, z. B. yyin, yyout, yylex und yytext.

Finite Zustandsmaschine

Das Standardgerüst für die finite Zustandsmaschine ist in /usr/ccs/lib/lex/ncform definiert. Der Benutzer kann eine persönlich konfigurierte finite Zustandsmaschine verwenden, indem er die Umgebungsvariable LEXER=PFAD setzt. Die Variable PFAD gibt den Pfad und den Dateinamen der benutzerdefinierten finiten Zustandsmaschine an. Der Befehl lex sucht in der Umgebung nach dieser Variablen und verwendet den angegebenen Pfad, sofern die Variable gesetzt ist.

Leerzeichen in einen Ausdruck einfügen

Normalerweise beenden Leer- oder Tabulatorzeichen eine Regel und damit auch den Ausdruck, der eine Regel definiert. Sie können die Leerzeichen oder Tabulatorzeichen jedoch in" "(Anführungszeichen), um sie in den Ausdruck einzuschließen. Verwenden Sie Anführungszeichen um alle Leerzeichen in Ausdrücken, die nicht bereits in Gruppen von[ ](eckige Klammern).

Sonstige Sonderzeichen

Das lex-Programm viele der normalen Sonderzeichen der Programmiersprache C. Diese Zeichenfolgen sind im Folgenden beschrieben:

Sequenz Bedeutung
\a Alert
\b Rückschritt
\f Formularvorschub
\n Zeilenvorschubzeichen (verwenden Sie nicht das aktuelle Zeilenvorschubzeichen in einem Ausdruck)
\r Rückgabe
\t Tabulator
\v Vertikaltabulator
\\ Backslash
\Ziffern Das Zeichen mit Codierung, das durch die für digits angegebene ein-, zwei- oder dreistellige oktale ganze Zahl dargestellt wird.
\xZiffern Das Zeichen mit Codierung, das durch die für digits angegebene Folge von Hexadezimalzeichen dargestellt wird.
\c Stellt, wenn c keines der zuvor aufgeführten Zeichen ist, das Zeichen c unverändert dar.

Anmerkung: Verwenden Sie \0 oder \x0 nicht in lex -Regeln.

Wenn Sie diese Sonderzeichen in einem Ausdruck verwenden, müssen Sie sie nicht in Anführungszeichen einschließen. Alle Zeichen mit Ausnahme dieser Sonderzeichen und der Operatorsymbole sind Textzeichen.

Abgleichsregel

Wenn die aktuelle Eingabe mehreren Ausdrücken entspricht, wählt der Befehl lex die längste Übereinstimmung zuerst aus. Wenn mehrere Regeln derselben Anzahl von Zeichen entsprechen, wählt der Befehl lex die zuerst vorkommende Regel aus. Angenommen, die Regeln

integer    keyword action...;
[a-z]+       identifier action...;

in dieser Reihenfolge angegeben sind undintegersDas Eingabewort lex stimmt mit der Eingabe als Kennung überein, da[a-z]+entspricht acht Zeichen, währendintegerentspricht nur sieben. Wenn die Eingabe jedoch "integer" ist, entsprechen beide Regeln sieben Zeichen. lex wählt die Regeln "keyword" aus, weil sie in der Reihenfolge zuerst vorkommt. Eine kürzere Eingabe, z. B.intstimmt nicht mit der Ausdrucksganzzahl überein. Daher wählt lex die ID-Regel aus.

Zeichenfolge mit Platzhalterzeichen abgleichen

Da lex die längste Übereinstimmung zuerst auswählt, verwenden Sie keine Regeln, die Ausdrücke wie die folgenden enthalten:.*. Beispiel:

'.*'

scheint eine gute Methode für die Erkennung von Zeichenfolgen in einfachen Anführungszeichen zu sein. Das Programm für lexikalische Analyse liest jedoch weit voraus und sucht nach einem entfernten einfachen Anführungszeichen, um eine lange Übereinstimmung zu finden. Wenn ein Programm für lexikalische Analyse mit einer solchen Regel die Eingabe

'first' quoted string here, 'second' here

ordnet es sie folgendermaßen zu:

'first' quoted string here, 'second'

Um die kleineren Zeichenfolgen zu finden,firstundsecondverwenden Sie die folgende Regel:

'[^'\n]*'

Diese Regel wird gestoppt nach'first'.

Fehler dieses Typs sind nicht weit reichende, weil die. (Punkt) Operator stimmt nicht mit einem Zeilenvorschubzeichen überein. Daher werden Ausdrücke wie.*(Punkt Stern) in der aktuellen Zeile stoppen. Versuchen Sie nicht, dies mit Ausdrücken wie [.\n]+. Das lexikalische Analyseprogramm versucht, die gesamte Eingabedatei zu lesen und es tritt ein interner Pufferüberlauf auf.

Zeichenfolgen mit Zeichenfolgen finden

Das Programm lex partitioniert den Eingabedatenstrom und sucht nicht nach allen möglichen Übereinstimmungen jedes Ausdrucks. Jedes Zeichen wird nur ein einziges Mal berücksichtigt. Zum Beispiel, um Vorkommen von beiden zu zählensheundheVerwenden Sie in einem Eingabetext die folgenden Regeln:

she         s++
he          h++
\n          |.           ;

Wo die letzten beiden Regeln alles ignorieren außerheundshe. Jedoch, weilsheumfassthe, erkennt lex nicht die Instanzen vonhedie enthalten sind inshe.

Um diese Auswahl zu überschreiben, verwenden Sie die Aktion REJECT. Diese Anweisung weist lex an, mit der nächsten Regel fortzufahren. lex setzt den Eingabezeiger dann auf die Position zurück, an der er sich vor der Ausführung der ersten Regel befand und führt die zweite Regel aus. Beispiel: Zum Zählen der eingeschlossenen Instanzen vonheVerwenden Sie die folgenden Regeln:

she                 {s++;REJECT;}
he                  {h++;REJECT;}
\n                  |.                   ;

Nach dem Zählen der Vorkommen vonshe, weist lex den Eingabedatenstrom zurück und zählt dann die Vorkommen vonhe. Weil in diesem FallsheumfasstheUmgekehrt können Sie die Aktion REJECT fürheIn anderen Fällen kann es schwierig sein, festzustellen, welche Eingabezeichen in beiden Klassen enthalten sind.

REJECT ist im Allgemeinen hilfreich, wenn lex den Eingabedatenstrom nicht partitionieren, sondern alle Beispiele einiger Elemente in der Eingabe erkennen soll und die Instanzen dieser Elemente sich überschneiden oder sich gegenseitig enthalten können.

Flags

Element Beschreibung
-C Erzeugt die Datei lex.yy.C anstelle von lex.yy.c für einen C++- Compiler. Verwenden Sie auch das Makro _CPP_IOSTREAMS, um die I/O Stream Library abzurufen.
-N Unterdrückt die Statistikzusammenfassung. Wenn Sie eigene Tabellengrößen für die finite Zustandsmaschine festlegen, erzeugt der Befehl "lex" diese Zusammenfassung automatisch, wenn Sie dieses Flag nicht auswählen.
-T Schreibt lex.yy.c in die Standardausgabe und nicht in eine Datei.
-v Enthält eine einzeilige Zusammenfassung der generierten Statistiken für die finite Zustandsmaschine.

Exitstatus

Dieser Befehl gibt die folgenden Exitwerte zurück:

Element Beschreibung
0 Erfolgreiche Ausführung.
>0 Es ist ein Fehler aufgetreten.

Beispiele

  1. Zum Zeichnen von lex -Anweisungen aus der DateilexcommandsStellen Sie die Ausgabe in lex.yy.cund verwenden Sie den folgenden Befehl:
    lex lexcommands
  2. Zum Erstellen eines lex -Programms, das Großbuchstaben in Kleinbuchstaben konvertiert, Leerzeichen am Ende einer Zeile entfernt und mehrere Leerzeichen durch einzelne Leerzeichen ersetzt. Dazu gehört Folgendes in einer lex -Befehlsdatei:
    %%
    [A-Z]   putchar(yytext[0]+ 'a'-'A');
    [ ]+$ ;
    [ ]+    putchar(' '); 

Dateien

Element Beschreibung
/usr/ccs/lib/libl.a Enthält die Laufzeitbibliothek.
/usr/ccs/lib/lex/ncform Definiert eine finite Zustandsmaschine.