Pegjs: Kemampuan untuk menentukan jumlah pengulangan (seperti di regexps)

Dibuat pada 11 Agu 2011  ·  22Komentar  ·  Sumber: pegjs/pegjs

Akan sangat membantu jika tata bahasa PEG.js mengizinkan sesuatu seperti ekspresi rentang ekspresi reguler dasar POSIX untuk digunakan. Misalnya:

  • "a"\{1,7\}

cocok dengan a , aa , ..., aaaaaaa

  • "a"\{0,1\}

cocok dengan string kosong dan a

  • "a"\{,6\}

cocok dengan string hingga (dan termasuk) enam a 's

  • "a"\{6,\}

cocok dengan string enam atau lebih a 's

  • "a"\{3\}

cocok hanya aaa , setara dengan "a"\{3,3\}

feature

Komentar yang paling membantu

Saya akan menyukai jumlah pengulangan juga. Tapi saya akan menyarankan sintaks yang sedikit berbeda. Pegasus hampir identik dengan pegjs, hanya untuk C#. Lihat di sini: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

Dan mereka mengimplementasikan fitur ini menggunakan ini: d<3> e<2,> f<1,5>

Semua 22 komentar

Saya tidak akan menerapkan fitur ini.

Alasan utamanya adalah tidak ada ruang dalam tata bahasa PEG.js untuk sintaks {m,n} — kurung kurawal sudah diambil untuk tindakan dan saya tidak ingin menggunakan garis miring terbalik seperti yang Anda sarankan (itu jelek dan tidak kompatibel dengan Perl regexps yang paling banyak digunakan sekarang dan juga sumber sintaks PEG.js lainnya) atau pembatas lainnya (yang akan membingungkan).

Dalam pengalaman saya, pengulangan terbatas semacam ini terjadi terutama pada bagian "leksikal" tata bahasa (aturan seperti color = "#" hexdigit hexdigit hexdigit hexdigit hexdigit hexdigit ) dan tidak terlalu sering. Saya pikir boleh saja menggunakan urutan ekspresi dan operator pengulangan yang ada ( * , + , ? ) di sana.

Saya telah mempertimbangkan kembali dan saya membuka kembali masalah ini. Tampaknya kemampuan untuk menentukan jumlah pengulangan yang sewenang-wenang sangat diinginkan oleh pengguna.

Saya ingin menghindari sintaks {m,n} seperti regexp karena { dan } sudah diambil untuk tindakan dan menggunakannya kembali akan menciptakan ambiguitas. Saat ini saya sedang memikirkan sesuatu seperti ini:

"foo" @ 1..10   // repeat 1 to 10 times
"foo" @ 1..     // repeat at least once
"foo" @ ..10    // repeat at most 10 times

Pertanyaan terbesar adalah seperti apa karakter pemisah itu dan bagaimana cara menandai rentang.

Untuk karakter pemisah, @ menurut saya bagus. Saya sedang mempertimbangkan % dan # , tetapi dalam pikiran saya yang pertama sudah dikaitkan dengan interpolasi string (misalnya dengan Python) dan yang kedua dengan komentar (dalam berbagai bahasa). Saya juga berpikir untuk melewatkan pemisah sepenuhnya:

"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

Untuk range markup, saya mengambil inspirasi di Ruby. Saya juga berpikir tentang - , tetapi kelihatannya terlalu mirip tanda minus. Di sisi lain, : seperti Python juga terlihat bagus untuk saya.

Saya tidak yakin tentang rentang setengah terbuka. Mungkin akan lebih baik untuk menandainya menggunakan + dan - seperti ini:

"foo" @ 1+    // repeat at least once
"foo" @ 10-   // repeat at most 10 times

Ada ide atau komentar?

Sangat keren bahwa Anda berencana untuk mendukung fitur ini!

Saya suka saran (default) Anda:
"foo" @ 1..10 // ulangi 1 sampai 10 kali
"foo" @ 1.. // ulangi setidaknya sekali
"foo" @ ..10 // ulangi paling banyak 10 kali

Saya tidak suka sintaks +/- untuk rentang setengah terbuka, sintaks titik ganda jauh lebih intuitif dan IMO mudah dibaca.

Satu-satunya hal yang saya pikirkan adalah menggunakan "#" vs "@", karena IMO "#" secara alami menyiratkan angka/penghitungan, sedangkan "@" secara alami menyiratkan referensi, jadi "#" mungkin sedikit lebih intuitif dan mudah dibaca (dan mungkin Anda bisa menggunakan "@" di masa depan untuk sesuatu?). Tapi itu benar-benar masalah kecil, dan saya akan senang dengan sintaks "@".

Bersulang!

Hanya komentar singkat: Saya pikir @ dan % adalah pilihan yang lebih baik daripada # karena penyorot sintaks yang tidak mendukung tata bahasa PEG.js, terutama yang mencoba menebak sintaks (misalnya penyorot kode Stack Overflow), kemungkinan akan menafsirkan # sebagai awal komentar, menyebabkannya ditampilkan—dengan menjengkelkan—dari titik itu hingga EOL dalam "warna komentar". Ini bukan preferensi berdasarkan logika dan penalaran, tentu saja, tetapi pada pragmatisme.

Bagaimana kalau kita kasus khusus untuk {num, num} sama? Yang AKAN berarti pengulangan, karena { , num} dan { num, } bukan kode js yang valid, dan {num, num} dan { num } tidak ada gunanya.

Mereka tidak mungkin bermakna bahkan jika tindakannya dalam bahasa lain.

Saya suka varian ini di antara yang disarankan (tapi ini terserah Anda untuk memilih, karena Anda penulisnya :) ):

// why we need separator, anyway? for me it looks very cool and simple to understand
"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

atau

"foo"@1..10   // repeat 1 to 10 times
"foo"@1..     // repeat at least once
"foo"@..10    // repeat at most 10 times

tapi yang kedua kurang disukai

ide x..y / ..y / x.. terlihat sangat keren, karena .. terlihat sebagai operator yang konsisten berkat itu.

+/- tidak ok untuk saya, karena mereka membingungkan dan menjadi operator tambahan di atas .. (dan + sudah digunakan)

Memikirkannya lagi. Apakah ini akan berhasil?

'foo'<1,5>
'foo'< ,3>
'foo'<2, >

karena < dan > saat ini tidak digunakan oleh tata bahasa

:+1: dari saya, itu terlihat bagus.

tentu saja, <,3> setara dengan <0,3> , jadi kami mungkin hanya memerlukan nomor minimum. Ini akan sesuai dengan apa yang telah dilakukan ECMA untuk ekspresi reguler JavaScript.

Saya suka <,> . Tetapi saya juga menyarankan penggunaan <3> sama dengan <3,3> .

Saya setuju, sintaks <> harus memetakan langsung ke perilaku {} di RegExp sebanyak mungkin.

Jika saya tidak salah, tidak perlu menambahkan pembatas apa pun, kecuali jika Anda ingin mengizinkan nama variabel dalam rentang.

foo 1,2 fighter
bar ,3 tender
baz 4, lurhmann
qux 5 quux

semua tidak ambigu.

@pygy , masalah dengan tidak menggunakan pembatas adalah berpotensi menghambat evolusi sintaks bahasa.

Misalnya, jika kita ingin menggunakan koma untuk sesuatu yang lain nanti, kita sekarang akan memiliki masalah dengan bentrokan sintaks di semua tempat. Membatasinya ke dalam kurung <> mengurangi luas permukaan koma dan angka secara substansial.

Plus, orang terbiasa menggunakan gaya {1,6} di RegExps.

Saya tidak merasa kuat tentang sintaks, tetapi saya menginginkan fitur ini, dan akan sangat bagus jika ekspresi dapat digunakan sebagai nilai rentang.

Kasus penggunaan saya: parsing literal dalam respons server IMAP, yang terlihat seperti {42}\r\n... , di mana 42 adalah jumlah karakter setelah baris baru yang mewakili string (ditampilkan di sini sebagai elipsis). Karena tidak ada pembatas akhir untuk literal IMAP, penghitungan karakter adalah satu-satunya cara untuk menguraikan respons ini.

Bagaimana dengan variabel dalam batasan? Ini sangat berguna untuk pesan dengan header, yang berisi panjangnya. Misalnya, tata bahasa

  = len:number message:.<len,len> .* {return message;}
number
  = n:[0-9] {return parseInt(n);}

harus mengurai

4[__] -> ['[', '_', '_', ']']
4[___] -> ['[', '_', '_', '_']
4[_] -> Error: expected 4 chars, got 3

Ini berguna untuk banyak protokol.

Mungkin menggunakan sintaks itu:
expression |min,max| , maka kurung sudut dapat digunakan untuk aturan template.

Apakah Anda masih mempertimbangkan untuk menerapkan ini?
Bagaimana dengan sesuatu yang mirip dengan rentang ABNF ?

exp *     // 0 or more times
exp 1*    // at least once
exp *10   // up to 10 times
exp 1*10  // 1 to 10 times

Halo. Saya memiliki format file yang kompleks untuk diuraikan. Ini adalah setengah biner, setengah ASCII.

Berikut versi masalah yang disederhanakan:

KK4TesRandom atau KK10TestATestBRandom

Logika:

<StringIndicator><StringLength><String><otherStuff>

KK adalah indikator untuk menandai string. Digit berikut (di sini 4 dan 10 ) adalah panjang string. Kemudian string itu sendiri (di sini Test dan TestATestB ). String tidak diakhiri oleh pola yang dapat diprediksi. Saya pada dasarnya harus menggunakan informasi panjang. Saya akan mengatakan ini adalah pola umum dalam format file biner tetapi apakah mungkin untuk menguraikan dengan tata bahasa saat ini?

Terima kasih.

Saya menerapkan hal seperti itu di cabang saya ranges-dynamic-boundary . Tata bahasa akan terlihat seperti ini:

start = len:nx data:.|len| { return data; };
nx = n:$[0-9]+ { return parseInt(n, 10); };

@Mingun wow! Itu bekerja seperti pesona! Terima kasih banyak atas implementasi Anda dan contoh singkatnya. Saya melakukan beberapa tes dan itu bekerja dengan luar biasa. Saya harap permintaan tarik Anda diterima oleh master.

Saya akan menyukai jumlah pengulangan juga. Tapi saya akan menyarankan sintaks yang sedikit berbeda. Pegasus hampir identik dengan pegjs, hanya untuk C#. Lihat di sini: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

Dan mereka mengimplementasikan fitur ini menggunakan ini: d<3> e<2,> f<1,5>

Apa pekerjaan orang-orang di sekitar untuk ini? Saya baru saja masuk ke PEGj sekarang, jadi mungkin saya mencoba memutar sekrup dengan palu, tetapi saya hanya mencoba mencocokkan antara 1 dan 6 digit :)

Saya menggunakan implementasi saya sendiri (lihat #267 untuk sintaks, solusi akhir mendukung angka, variabel, dan blok kode sebagai batasan) dan saya akan segera menyiapkan PR untuk Peggy (rebranding garpu PEG.js yang dipertahankan)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat