2015-04-21 7 views
14

Ich habe begonnen, ANTLR zu benutzen und habe festgestellt, dass es mit seinen Lexer-Regeln ziemlich unbeständig ist. Ein äußerst frustrierend Beispiel ist das folgende:ANTLR 4.5 - Nicht übereinstimmender Eingang 'x' erwartet 'x'

grammar output; 

test: FILEPATH NEWLINE TITLE ; 

FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ; 
NEWLINE: '\r'? '\n' ; 
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ; 

Diese Grammatik wird so etwas wie nicht überein:

c: \ test.txt
x

Merkwürdig, wenn ich TITLE ändern TITLE: 'x' ; es noch sein versäumt es diesmal, eine Fehlermeldung zu geben, die sagt: "nicht übereinstimmende Eingabe 'x' erwartet 'x'" was sehr verwirrend ist. Noch seltsamer, wenn ich die Verwendung von TITLE in test durch FILEPATH ersetze, funktioniert die ganze Sache (obwohl FILEPATH mehr zusammenpassen wird, als ich suche, um zusammenzupassen, so ist es im Allgemeinen keine gültige Lösung für mich).

Ich bin sehr verwirrt darüber, warum ANTLR so extrem seltsame Fehler gibt und dann plötzlich ohne ersichtlichen Grund arbeitet, wenn man Dinge herumschlurft.

Antwort

31

Dies scheint ein weit verbreitetes Missverständnis von ANTLR zu sein:

Sprachverarbeitung in ANTLR:

Die Sprachverarbeitung in zwei streng getrennten Phasen erfolgt:

  • Lexing, dh Partitionierung der Text in Token
  • Parsen, dh Erstellen eines Parserbaums aus den Tokens

Da das Lexing dem Parsing vorausgehen muss, gibt es eine Konsequenz: Der Lexer ist unabhängig vom Parser, der Parser kann den Lexing nicht beeinflussen.

Lexing

Lexing in ANTLR arbeitet wie folgt:

  • alle Regeln mit Groß ersten Zeichen sind Lexer Regeln
  • die Lexer am Anfang startet und versucht, eine Regel zu finden, die passt am besten zum aktuellen Eingang
  • ein bester Treffer ist ein Übereinstimmung, die maximale Länge hat, dhdas Token, das von Anhängen des nächsten Eingabezeichen auf die maximale Länge Spielergebnisse wird von keiner LEXER Regel
  • Tokens werden von Übereinstimmungen erzeugt Ergebnisse:
    • wenn eine Regel die maximalen Länge entspricht Spiel die entsprechende Token in den Tokenstrom geschoben
    • wenn mehrere Regeln das maximale Länge Spiel entsprechen die ersten definierte Token in der Grammatik zu dem Token Strom gedrückt werden

Beispiel: Was ist mit Ihrer Grammatik

Ihre Grammatik hat zwei Regeln falsch ist, die kritisch sind:

FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ; 
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ; 

Jedes Spiel, dass durch TITEL abgestimmt ist, wird auch durch abgestimmt werden DATEIPFAD. Und FILEPATH ist vor TITLE definiert: Also jedes Token, das Sie als Titel erwarten, wäre ein FILEPATH.

Es gibt zwei Hinweise dafür:

  • halten Sie Ihre Lexer disjunct Regeln (kein Token sollte eine Ober eines anderen entsprechen)
  • wenn Ihr Token absichtlich die gleichen Strings entsprechen, als sie in die setzen richtige Reihenfolge (in Ihrem Fall wird dies ausreichen).
  • wenn Sie benötigen einen Parser angetrieben Lexer Sie zu einem anderen Parser-Generator ändern müssen: PEG-Parsers oder GLR-Parsers wird das tun (aber natürlich diese andere Probleme erzeugen können)
+3

Das sehr viel Sinn macht jetzt, danke für deine Antwort! Es wäre jedoch nett, eine hilfreichere Fehlermeldung zu haben, aber ich weiß, dass das schwierig oder unangemessen sein kann. –

+0

Zur Laufzeit muss der Parser davon ausgehen, dass sich der Benutzer dessen Verhaltens bewusst ist. Dennoch stimme ich zu, dass eine Warnung in Ordnung wäre, wenn sich zwei Lexer-Regeln auf diese Weise überschneiden würden. – CoronA

+1

Große Zusammenfassung von ANTLR Referenz! – Cody

Verwandte Themen