Temukan set ikuti

14

Tantangan di bawah ini mengharuskan Anda untuk terbiasa dengan teori parser formal. Jika Anda tidak tahu apa pertanyaannya karena Anda tidak tahu apa arti istilah tersebut, tata bahasa bebas konteks dan set pertama / ikuti tercakup dalam banyak program universitas.

Saya dapat merekomendasikan kursus Stanford ini , khususnya materi 08 dan 09 (dari halaman 7). Saya telah mengekstraksi juga mengekstraksi lembar contekan dari selebaran ini - Saya sarankan siapa pun yang mencoba tantangan ini untuk membacanya .


Menulis sebuah program atau fungsi yang diberikan tata bahasa bebas konteks menemukan set ikuti dari setiap nonterminal. Secara informal, rangkaian follow dari nonterminal adalah serangkaian terminal dan $(artinya end-of-input) yang dapat Anda temukan setelah terminal itu dalam kalimat yang valid.

Input diberikan sebagai string ASCII yang dapat dicetak atau larik jalur ASCII yang dapat dicetak. Anda dapat menampilkan set dalam format yang wajar, menggunakan $(baik sebagai output literal, atau string di dalam set, dll) untuk menunjukkan akhir input. Anda dapat mengasumsikan bahwa input selalu valid sesuai dengan format di bawah ini.

Tata bahasa gratis konteks diberikan dengan cara yang sangat sederhana. Setiap baris berisi satu produksi. Setiap produksi adalah daftar simbol yang dipisahkan ruang. Terminal adalah serangkaian karakter yang dikelilingi oleh tanda kutip (misalnya '**'). Untuk kesederhanaan Anda dapat mengasumsikan bahwa terminal tidak mengandung spasi, tetapi alangkah baiknya jika program Anda mengizinkannya. Nonterminal dapat berupa string apa pun yang tidak mengandung spasi atau $. Produksi kosong (biasanya ditunjukkan dengan ε) hanyalah garis yang hanya berisi sisi kiri nonterminal. Baris pertama adalah produksi yang mendefinisikan simbol awal.

Sebagai contoh, tata bahasa berikut:

S → aSa | bSb | ε

Akan diberikan sebagai:

S 'a' S 'a'
S 'b' S 'b'
S

Contoh input / output:

In:
S 'a' S 'a'
S 'b' S 'b'
S

Out:
S {'a', 'b', $}

In:
S A B C
A 'a'
A C 'b'
A
B C
B 'd' A
B
C 'e'
C 'f' 

Out:
S {$}
A {'d', 'e', 'f'}
B {'e', 'f'}
C {'b', 'e', 'f', $}

In:
Start Alice Bob
Alice Charlie 'a'
Alice
Bob Bob 'a' Alice Charlie
Bob '!!!'
Charlie 'b'
Charlie

Out:
Start {$}
Alice {'a', '!!!', 'b', $}
Bob {'a', $}
Charlie {'a', $}

Kode terpendek dalam byte menang.

orlp
sumber
4
Dengan asumsi bahwa orang tahu apa konteks tata bahasa gratis itu tampaknya baik, tapi saya pikir itu tidak akan menyakiti tantangan jika Anda memasukkan definisi tindak yang ditetapkan di sini, bukan hanya menghubungkan ke sana.
Martin Ender
1
Ini membawa kembali beberapa kenangan dari " Konstruksi Kompiler " di universitas, di mana kami harus menyelesaikan banyak tugas serupa.
insertusernamehere

Jawaban:

3

Perl, 257 byte

Termasuk +4 untuk -0p

Berikan tata bahasa pada STDIN (tanpa spasi tambahan. Pastikan untuk menghapus ruang ekstra pada contoh kedua). Asumsikan nama non-terminal hanya berisi huruf, angka, dan _. Menggunakan #bukannya $mengindikasikan akhir input. Dapat menangani literal yang berisi spasi

perl -M5.010 follow.pl
E T e
e '+' T e
e
T F t
t '*' F t
t
F '(' E ')'
F 'id'
^D

Keluarkan set ikuti sebagai daftar non-terminal literaltanpa urutan tertentu. Untuk contoh di atas output:

F ')'
F #
t ')'
t #
T ')'
T #
F '+'
t '+'
T '+'
F '*'
e ')'
e #
E ')'
E #

follow.pl:

#!/usr/bin/perl -0n
s/'.*?'/~$&/eg;s% (?=(\w.*\n))%$_.=">$1"%reg;/\s/;$_.=">$` #\n";s%^((\w+)\K ?\S*).*%$s{$1}++||"\$a.=s/ $2\\b/$&/rg"%eemgr,s%^(\w+ ).*?(\w+)$%"\$a.=s/>$1/>$2 /rg"%eermg,$_.=$a,s%>.*\xd8\K .*%%g,s%.+\n%$&x!/\n$&/g%eg until$$_++;s/\xd8.*?\xd8/~$&/eg;say/>(\w+ \W\S*\n)/g

Berfungsi seperti yang ditunjukkan, tetapi ganti \xd8dan \ndengan versi literalnya untuk mendapatkan skor yang diklaim.

Harus dimungkinkan untuk meningkatkan ini karena mengonversi firstset ke followset saat ini sangat canggung.

Ton Hospel
sumber