Was bedeutet Fragment in ANTLR?
Ich habe beide Regeln gesehen:
fragment DIGIT : '0'..'9';
und
DIGIT : '0'..'9';
Was ist der Unterschied?
Ein Fragment ähnelt in gewisser Weise einer Inline-Funktion: Es macht die Grammatik lesbarer und einfacher zu pflegen.
Ein Fragment wird niemals als Token gezählt, es dient nur zur Vereinfachung einer Grammatik.
Erwägen:
NUMBER: DIGITS | OCTAL_DIGITS | HEX_DIGITS;
fragment DIGITS: '1'..'9' '0'..'9'*;
fragment OCTAL_DIGITS: '0' '0'..'7'+;
fragment HEX_DIGITS: '0x' ('0'..'9' | 'a'..'f' | 'A'..'F')+;
In diesem Beispiel gibt das Abgleichen einer NUMMER immer eine NUMMER an den Lexer zurück, unabhängig davon, ob sie mit "1234", "0xab12" oder "0777" übereinstimmt.
fragment
in ANTLR bedeutet. Das Beispiel, das Sie geben, ist jedoch schlecht: Sie möchten nicht, dass ein Lexer einNUMBER
Token erzeugt, das eine Hex-, Dezimal- oder Oktalzahl sein kann. Das würde bedeuten, dass Sie dasNUMBER
Token in einer Produktion überprüfen müssen (Parser-Regel). Sie könnten besser die Lexer produzieren lassenINT
,OCT
undHEX
Token und eine Produktionsregel erstellen:number : INT | OCT | HEX;
. In einem solchen BeispielDIGIT
könnte a ein Fragment sein, das von den TokenINT
und verwendet wirdHEX
.Laut dem Definitive Antlr4-Nachschlagewerk:
Tatsächlich verbessern sie die Lesbarkeit Ihrer Grammatiken.
Schauen Sie sich dieses Beispiel an:
STRING ist ein Lexer, der eine Fragmentregel wie ESC verwendet. Unnicode wird in der Esc-Regel und Hex wird in der Unicode-Fragmentregel verwendet. ESC-, UNICODE- und HEX-Regeln können nicht explizit verwendet werden.
quelle
Die endgültige ANTLR 4-Referenz (Seite 106):
Abstrakte Konzepte:
Fall 1: (wenn ich die Entitäten RULE1, RULE2, RULE3 oder Gruppeninformationen benötige )
Fall 2: (Wenn mir RULE1, RULE2, RULE3 egal sind, konzentriere ich mich nur auf RULE0)
Fall3: (entspricht Fall2 und ist daher besser lesbar als Fall2)
Unterschiede zwischen Fall1 und Fall2 / 3?
Sehen wir uns ein konkretes Beispiel an.
Ziel: Identifizierung
[ABC]+
,[DEF]+
,[GHI]+
Tokeninput.txt
Main.py.
Fall 1 und Ergebnisse:
Alphabet.g4 (Fall1)
Ergebnis:
Fall 2/3 und Ergebnisse:
Alphabet.g4 (Fall2)
Alphabet.g4 (Fall3)
Ergebnis:
Haben Sie Teile "Gruppen erfassen" und "Gruppen nicht erfassen" gesehen ?
Sehen wir uns das konkrete Beispiel2 an.
Ziel: Identifizieren Sie Oktal- / Dezimal- / Hexadezimalzahlen
input.txt
Nummer.g4
Main.py.
Ergebnis:
Wenn Sie den Modifikator ‚Fragment‘ hinzufügen
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, werden Sie nicht in der Lage sein , die Zahl Einheiten zu erfassen (da sie nicht sind Zeichen mehr). Und das Ergebnis wird sein:quelle
Dieser Blog-Beitrag enthält ein sehr klares Beispiel, in dem
fragment
ein wesentlicher Unterschied gemacht wird:Die Grammatik erkennt '42', aber nicht '7'. Sie können das Problem beheben, indem Sie die Ziffer zu einem Fragment machen (oder DIGIT nach INT verschieben).
quelle
fragment
, sondern die Reihenfolge der Lexerregeln.DIGIT
als Fragment vonINT
das Problem löst, nur weil Fragmente keine Token definieren und somitINT
die erste lexikalische Regel bilden. Ich stimme Ihnen zu, dass dies ein aussagekräftiges Beispiel ist, aber (imo) nur für diejenigen, die bereits wissen, was dasfragment
Schlüsselwort bedeutet. Ich finde es etwas irreführend für jemanden, der zum ersten Mal versucht, die richtige Verwendung von Fragmenten herauszufinden.