Die Antlr-Implementierung (und die meisten Compiler/Compiler-Generatoren) verwenden das Konzept eines separaten Lexers und Parsers, meist aus Leistungsgründen. In diesem Modell ist der Lexer dafür verantwortlich, die tatsächlichen Zeichen in der Eingabezeichenfolge zu lesen und eine Liste der gefundenen Token in einer präziseren Repräsentation, wie z. B. einem enum oder int-codes für jedes Token, zurückzugeben. Der Parser arbeitet an diesen Token anstelle der ursprünglichen Eingabe, um die Implementierung und Leistung zu erleichtern.
Es gibt zwei Möglichkeiten, die Verwendung eines Tokens in Antlr zu "deklarieren", eine ist explizit und hat eine reguläre Musterausprägung, die andere ist implizit, ist immer eine feste Zeichenkette.
ExplicitRegExp: [A-Z][a-z]+; // lexer rule starts with uppercase letter
ExplicitFixed: 'fixed';
parserRule: 'implicit' ExplicitRegExp; // parser rules starts with lowercase letter
Wenn ein Token explizit deklarieren, wird es einen int-Code zugeordnet, in der Parsing-Zustandsmaschine verwendet werden. Nehmen wir an, ExplicitRegExp
wird 1 und ExplicitFixed
wird 2. Aber der Parser wird auch die implicit
Tokens benötigen, um die Grammatik richtig analysieren zu können, so dass der implicit
Token den Code 3 implizit zugewiesen wird.
Wie ist das schlimm? Sie können Fehler in den verschiedenen Teilen der Grammatik:
a : 'implicit' c;
b : 'implcit' d; // typo here
Und Ihre Grammatik wird nicht wie erwartet funktionieren, weil implcit
wird ein gültiges Token sein, zugewiesen der int-Code 4. Es macht auch Ihre Grammatik/Lexer härter zu debuggen aufgrund von automatisch generierenden Antlr-Namen für die impliziten Regeln, wie T___0
. Eine andere Sache ist, dass Sie die Reihenfolge der Lexer-Regeln verlieren, die könnte einen Unterschied machen (in der Regel nicht, weil implizite Token alle festen Inhalt sind).
Der Antlr Compiler könnte wählen Sie eine Fehlermeldung zu geben und verlangen, dass Sie die Token explizit zu schreiben, aber es wählt sie gehen zu lassen und warnen Sie nur, dass Sie sollten nicht zu, dass, wahrscheinlich für das Prototyping/Testzwecken.
zu lassen Antlr glücklich sein, ist es die ausführliche Art und Weise tun und alle Ihre Token erklären:
grammar SimpleTest;
top: library | module ;
library: 'library' library_name=IDENTIFIER ';' ; // I'm using aliasing instead of different parser rule here, just a preference
module: 'module' module_name=IDENTIFIER ';' ;
MODULE: 'module' ;
LIBRARY: 'library' ;
IDENTIFIER: [a-zA-Z0-9]+;
Dann macht es keinen Unterschied, ob Sie eine feste Token von seinem expliziten Namen (wie MODULE
) verweisen oder von sein Inhalt (wie 'module'
).
Sie können es explizit machen und immer noch den tatsächlichen Token-Text verwenden: 'library: 'library library_name'; ' ; LIBRARYTK: 'Bibliothek'; 'um die Warnung zu entfernen. Die Warnung wird wahrscheinlich ausgegeben, weil es sich um einen Tippfehler oder ähnliches handeln könnte - keine Warnungen, jeder Ort in der Grammatik verwendet das richtige Token. – Mephy
@Mephy: wow, danke dafür, das hilft mir bei den Warnungen :-)! Dies erhöht jedoch immer noch die Anzahl der Token in SimpleTest.tokens. – TFuto
Sie brauchen das Token nicht - aber der Parser tut es, also gibt der Lexer es aus. Sie müssen die ausgegebenen Token nicht an die Verwendung der Grammatik anpassen, sondern konzentrieren Sie sich stattdessen auf den abstrakten Syntaxbaum. – Mephy