Co oznacza fragment w ANTLR?
Widziałem obie zasady:
fragment DIGIT : '0'..'9';
i
DIGIT : '0'..'9';
Jaka jest różnica?
Fragment jest nieco podobny do funkcji wbudowanej: sprawia, że gramatyka jest bardziej czytelna i łatwiejsza w utrzymaniu.
Fragment nigdy nie będzie liczony jako token, służy jedynie uproszczeniu gramatyki.
Rozważać:
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')+;
W tym przykładzie dopasowanie LICZBY zawsze zwróci lekserowi LICZBĘ, niezależnie od tego, czy pasuje do „1234”, „0xab12” czy „0777”.
fragment
znaczenia w ANTLR. Ale przykład, który podajesz, jest kiepski: nie chcesz, aby lekser tworzyłNUMBER
token, który może być liczbą szesnastkową, dziesiętną lub ósemkową. Oznaczałoby to, że musiałbyś sprawdzićNUMBER
token w produkcji (reguła parsera). Można lepiej niech produce lexerINT
,OCT
orazHEX
znaki i utworzyć regułę produkcji:number : INT | OCT | HEX;
. W takim przykładzie aDIGIT
może być fragmentem, który będzie używany przez tokenyINT
iHEX
.Według książki referencyjnej Definitive Antlr4:
w rzeczywistości poprawią czytelność twoich gramatyk.
spójrz na ten przykład:
STRING to lekser używający reguły fragmentów, takiej jak ESC. Unicode jest używany w regule Esc, a Hex jest używany w regule fragmentów Unicode. Reguł ESC, UNICODE i HEX nie można używać jawnie.
źródło
The Definitive ANTLR 4 Reference (Strona 106) :
Abstrakcyjne koncepcje:
Przypadek 1: (jeśli muszę RULE1, RULE2, RULE3 podmioty lub informacji o grupie)
Przypadek2: (jeśli nie obchodzi mnie RULE1, RULE2, RULE3, skupiam się tylko na RULE0)
Przypadek3: (jest odpowiednikiem przypadku2, dzięki czemu jest bardziej czytelny niż przypadek2)
Różnice między przypadkiem 1 i przypadkiem 2/3?
Zobaczmy konkretny przykład.
Cel: zidentyfikować
[ABC]+
,[DEF]+
,[GHI]+
tokenyinput.txt
Main.py
Przypadek 1 i wyniki:
Alphabet.g4 (przypadek 1)
Wynik:
Przypadek 2/3 i wyniki:
Alphabet.g4 (Case2)
Alphabet.g4 (Case3)
Wynik:
Czy widziałeś części „grup przechwytywania” i „grup nieprzechwytywanych” ?
Zobaczmy konkretny przykład 2.
Cel: zidentyfikuj liczby ósemkowe / dziesiętne / szesnastkowe
input.txt
Liczba g4
Main.py
Wynik:
Jeśli dodać modyfikator „fragment” do
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, nie będzie w stanie uchwycić żywe numer (ponieważ nie są one już żetony). Rezultatem będzie:źródło
Ten post na blogu zawiera bardzo wyraźny przykład, w którym
fragment
ma znaczenie:Gramatyka rozpoznaje „42”, ale nie „7”. Możesz to naprawić, tworząc fragment cyfry (lub przesuwając DIGIT po INT).
źródło
fragment
, ale kolejność reguł leksera.DIGIT
jako fragmentuINT
rozwiązuje problem tylko dlatego, że fragmenty nie definiują tokenów, tworząc w ten sposóbINT
pierwszą regułę leksykalną. Zgadzam się z tobą, że jest to znaczący przykład, ale (imo) tylko dla tych, którzy już wiedzą, cofragment
oznacza słowo kluczowe. Uważam to za nieco mylące dla kogoś, kto po raz pierwszy próbuje znaleźć prawidłowe użycie fragmentów.