2016-04-19 9 views
2

Was sind die Vor- und Nachteile der Verwendung expliziter Token-Definitionen in ANTLR4? Ich finde den Text in einzelnen Klammern beschreibender und einfacher zu verwenden als einen separaten Token zu erstellen und diesen anstelle des Textes zu verwenden.ANTLR4: implizite oder explizite Token-Definition

ZB:

grammar SimpleTest; 

top: library | module ; 

library: 'library' library_name ';' ; 
library_name: IDENTIFIER;   

module: MODULE module_name ';' ; 
module_name: IDENTIFIER; 

MODULE: 'module' ; 
IDENTIFIER: [a-zA-Z0-9]+; 

Die generierten Token sind:

T__0=1 
T__1=2 
MODULE=3 
IDENTIFIER=4 
'library'=1 
';'=2 
'module'=3 

Wenn ich nicht daran interessiert bin in der 'library' "Token", da bereits die Regel, was etabliert ich gegen mich passend, und ich Überspringe es trotzdem, macht es Sinn, es durch LIBRARY und eine Token-Deklaration zu ersetzen? (Die Anzahl der Token wird dann wachsen.) Warum ist dies eine Warnung in ANTLRWorks?

+1

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

+0

@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

+0

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

Antwort

4

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').

+0

Danke, Mephy! :-) – TFuto

+0

Es gibt noch mehr: Implizite Token erhalten automatisch generierte Namen (wie T__0 vom OP). In Ihrem Code können Sie nie wissen, welcher von ihnen welcher Token ist. Bei expliziten Definitionen definieren Sie auch den Namen des Tokens in Ihrer Zielsprache. –

+0

Und die Reihenfolge der Lexer-Regeln ist ebenfalls wichtig, was mit impliziten Tokens schlecht managbar ist. – Divisadero

2

Eigentlich gibt es einen Unterschied zwischen impliziten und expliziten Token:

Von "The Definitive ANTLR4 Reference", Seite 76:

ANTLR sammelt und alle der Stringliterale und Lexer Regeln trennt aus den Parser-Regeln. Literale wie 'enum' werden lexikalisch Regeln und gehen sofort nach den Parser-Regeln, aber vor den expliziten lexikalischen Regeln.

ANTLR-Lexer lösen Mehrdeutigkeiten zwischen lexikalischen Regeln, indem sie die zuerst angegebene Regel favorisieren.

Highlight von mir.

Verwandte Themen