Apa arti fragmen di ANTLR?
Saya telah melihat kedua aturan tersebut:
fragment DIGIT : '0'..'9';
dan
DIGIT : '0'..'9';
Apa bedanya?
Fragmen agak mirip dengan fungsi sebaris: Fragmen membuat tata bahasa lebih mudah dibaca dan dikelola.
Fragmen tidak akan pernah dihitung sebagai token, ini hanya berfungsi untuk menyederhanakan tata bahasa.
Mempertimbangkan:
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')+;
Dalam contoh ini, mencocokkan NOMOR akan selalu mengembalikan NOMOR ke lexer, terlepas dari apakah itu cocok dengan "1234", "0xab12", atau "0777".
fragment
artinya di ANTLR. Tetapi contoh yang Anda berikan salah: Anda tidak ingin lexer menghasilkanNUMBER
token yang dapat berupa bilangan heksadesimal, desimal, atau oktal. Itu berarti Anda perlu memeriksaNUMBER
token dalam produksi (aturan parser). Anda bisa lebih baik membiarkan lexer hasilINT
,OCT
danHEX
token dan membuat aturan produksi:number : INT | OCT | HEX;
. Dalam contoh seperti itu, aDIGIT
bisa menjadi fragmen yang akan digunakan oleh tokenINT
danHEX
.Menurut buku referensi Definitive Antlr4:
sebenarnya mereka akan meningkatkan keterbacaan tata bahasa Anda.
lihat contoh ini:
STRING adalah lexer yang menggunakan aturan fragmen seperti ESC. Unicode digunakan dalam aturan Esc dan Hex digunakan dalam aturan fragmen Unicode. Aturan ESC dan UNICODE dan HEX tidak dapat digunakan secara eksplisit.
sumber
Referensi Definitif ANTLR 4 (Halaman 106) :
Konsep abstrak:
Kasus1: (jika saya membutuhkan RULE1, RULE2, entitas RULE3 atau info grup)
Case2: (jika saya tidak peduli RULE1, RULE2, RULE3, saya hanya fokus pada RULE0)
Case3: (setara dengan Case2, membuatnya lebih mudah dibaca daripada Case2)
Perbedaan antara Case1 dan Case2 / 3?
Mari kita lihat contoh konkretnya.
Tujuan: mengidentifikasi
[ABC]+
,[DEF]+
,[GHI]+
tokeninput.txt
Main.py
Kasus1 dan hasil:
Alphabet.g4 (Kasus1)
Hasil:
Kasus2 / 3 dan hasil:
Alphabet.g4 (Case2)
Alphabet.g4 (Case3)
Hasil:
Apakah Anda melihat bagian "grup penangkap" dan "grup bukan penangkap" ?
Mari kita lihat contoh konkret2.
Sasaran: mengidentifikasi bilangan oktal / desimal / heksadesimal
input.txt
Nomor.g4
Main.py
Hasil:
Jika Anda menambahkan modifier 'fragmen' untuk
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, Anda tidak akan dapat menangkap entitas jumlah (karena mereka tidak token lagi). Dan hasilnya adalah:sumber
Posting blog ini memiliki contoh yang sangat jelas yang
fragment
membuat perbedaan yang signifikan:Tata bahasanya akan mengenali '42' tapi bukan '7'. Anda dapat memperbaikinya dengan membuat digit menjadi fragmen (atau memindahkan DIGIT setelah INT).
sumber
fragment
, tetapi urutan aturan lexer.DIGIT
sebagai fragmen dariINT
memecahkan masalah hanya karena fragmen tidak mendefinisikan token, sehingga membuatINT
aturan leksikal pertama. Saya setuju dengan Anda bahwa ini adalah contoh yang berarti tetapi (imo) hanya untuk yang sudah tahu apa artifragment
kata kunci itu. Saya merasa agak menyesatkan bagi seseorang yang mencoba mencari tahu penggunaan fragmen yang benar untuk pertama kalinya.