Lassen Sie uns die Funktionsweise eines lexikalischen Analysators (auch Scanner genannt) sehen.
Nehmen wir einen Beispielausdruck:
INPUT : cout << 3+2+3;
FORMATTING PERFORMED BY SCANNER : {cout}|space|{<<}|space|{3}{+}{2}{+}{3}{;}
nicht die tatsächliche Ausgabe.
Der Scanner sucht einfach wiederholt nach einem Lexem im Quellprogrammtext, bis der Eingang erschöpft ist
Lexem ist eine Teilzeichenfolge der Eingabe, die eine gültige Folge von Terminals bildet, die in der Grammatik vorhanden sind. Jedes Lexem folgt einem Muster, das am Ende erklärt wird (der Teil, den der Leser zuletzt überspringen darf).
(Wichtige Regel ist, nach dem längstmöglichen Präfix zu suchen, das eine gültige Folge von Terminals bildet, bis das nächste Leerzeichen angetroffen wird ... siehe unten)
LEXEME:
- cout
- <<
(Obwohl "<" auch eine gültige Terminalzeichenfolge ist, muss die oben genannte Regel das Muster für das Lexem "<<" auswählen, um ein vom Scanner zurückgegebenes Token zu generieren.)
- 3
- +
- 2
- ;;
Token: Token werden jedes Mal einzeln zurückgegeben (vom Scanner, wenn dies vom Parser angefordert wird), wenn der Scanner ein (gültiges) Lexem findet. Der Scanner erstellt, falls noch nicht vorhanden, einen Symboltabelleneintrag (mit Attributen: hauptsächlich Token-Kategorie und wenige andere) , wenn er ein Lexem findet, um dessen Token zu generieren
'#' bezeichnet einen Symboltabelleneintrag. Ich habe zum besseren Verständnis auf die Lexemnummer in der obigen Liste hingewiesen, aber es sollte technisch gesehen der tatsächliche Index der Aufzeichnung in der Symboltabelle sein.
Die folgenden Token werden vom Scanner in der angegebenen Reihenfolge für das obige Beispiel an den Parser zurückgegeben.
<Kennung, # 1>
<Operator, # 2>
<Literal, # 3>
<Operator, # 4>
<Literal, # 5>
<Operator, # 4>
<Literal, # 3>
<Interpunktionszeichen, # 6>
Wie Sie den Unterschied sehen können, ist ein Token ein Paar im Gegensatz zu Lexem, das eine Teilzeichenfolge der Eingabe ist.
Und das erste Element des Paares ist die Token-Klasse / Kategorie
Token-Klassen sind unten aufgeführt:
SCHLÜSSELWÖRTER
IDENTIFIKATOREN
LITERALE
PUNKTUATOREN
BETREIBER
Und noch etwas: Der Scanner erkennt Leerzeichen, ignoriert sie und bildet überhaupt kein Token für ein Leerzeichen. Nicht alle Trennzeichen sind Leerzeichen. Ein Leerzeichen ist eine Form von Trennzeichen, die von Scannern für diesen Zweck verwendet wird. Tabulatoren, Zeilenumbrüche, Leerzeichen und Escapezeichen in der Eingabe werden zusammen als Leerzeichen-Trennzeichen bezeichnet. Nur wenige andere Trennzeichen sind ';' ',' ':' usw., die allgemein als Lexeme anerkannt sind, die Token bilden.
Die Gesamtzahl der zurückgegebenen Token beträgt hier 8, es werden jedoch nur 6 Symboltabelleneinträge für Lexeme vorgenommen. Lexeme sind auch insgesamt 8 (siehe Definition des Lexems)
--- Sie können diesen Teil überspringen
A ***pattern*** is a rule ( say, a regular expression ) that is used to check if a string-of-terminals is valid or not
.
If a substring of input composed only of grammar terminals is
following the rule specified by any of the listed patterns , it is
validated as a lexeme and selected pattern will identify the category
of lexeme, else a lexical error is reported due to either (i) not
following any of the rules or (ii) input consists of a bad
terminal-character not present in grammar itself.
for example :
1. No Pattern Exists : In C++ , "99Id_Var" is grammar-supported string-of-terminals but is not recognised by any of patterns hence lexical error is reported .
2. Bad Input Character : $,@,unicode characters may not be supported as a valid character in few programming languages.`