Pegjs: Izinkan pengembalian hasil kecocokan dari ekspresi tertentu dalam aturan tanpa tindakan

Dibuat pada 23 Mei 2016  ·  10Komentar  ·  Sumber: pegjs/pegjs

Sangat umum untuk mengembalikan nilai dari salah satu non-terminal dalam aturan atau di dalam sub-aturan yang diberi tanda kurung. Sebagai contoh:

varDecl = type:type id:ID init:( EQ e:expr {return e} )?
                { return scopedAST('VARDECL', {type, id, init}) }

Dalam hal ini, saya memerlukan expr berlabel e di dalam level kurung init untuk frasa opsional dalam bahasa tersebut. Saya tidak membutuhkan "kata kebisingan" EQ sebagai bagian dari nilai yang dikembalikan.

Jika bahasa PEGjs memiliki simbol yang akan digunakan untuk menandai terminal seperti expr atas sehingga mereka, dan hanya mereka, adalah nilai yang dikembalikan dari aturan tata bahasa atau sub-aturan, kasus ini akan lebih sederhana.

Untuk menulis ulang contoh saya di atas:

varDecl = type:type id:ID init:( EQ ^expr )?
                { return scopedAST('VARDECL', {type, id, init}) }

Perhatikan penggunaan ^ untuk menandai nilai expr di dalam init tanda kurung opsional frase sub-aturan untuk menunjuk apa yang terikat init . Ini menyederhanakan banyak situasi baik dengan dan tanpa sub-aturan dalam kurung yang ditunjukkan dalam contoh ini.

Terima kasih telah membuat alat yang sangat sederhana, elegan, dan kuat. Saya suka PEGj! :senyum:

feature

Semua 10 komentar

Cintai ide itu! ^ juga sangat intuitif.

Ini juga bisa bekerja pada aturan yang tidak bersarang:

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = WhiteSpace? ^Identifier WhiteSpace?

Sangat mudah dibaca! Agaknya, penggunaan beberapa ^ juga akan berfungsi, sehingga:

a = ^b  c  ^d  e

Akan mengembalikan [b, d] ? Sepertinya masuk akal.

Demikian juga, tampaknya masuk akal bahwa jika dicampur dengan tangkapan bernama, aturan ^ diabaikan, jadi

x = a ^b foo:c { return foo; }

Akan kembali hanya c.

Oh, ide kelipatan itu bagus sekali. Mencampur dengan tangkapan bernama seharusnya
sebuah kesalahan.

Pada Tue, Jul 5, 2016, 1:07 Graham Wakefield [email protected]
menulis:

Sangat mudah dibaca! Agaknya, penggunaan beberapa ^ juga akan berfungsi, sehingga:

a = ^bc ^de

Akan kembali [b, d]? Sepertinya masuk akal.

Demikian juga, tampaknya masuk akal jika dicampur dengan tangkapan bernama, ^
aturan diabaikan:

x = a ^b foo:c { kembalikan foo; }


Anda menerima ini karena Anda yang menulis utas.

Balas email ini secara langsung, lihat di GitHub
https://github.com/pegjs/pegjs/issues/427#issuecomment -230413015, atau bisukan
benang
https://github.com/notifications/unsubscribe/ABC26k8v0DIzuWUlkoDZGm2ep10Y5bcMks5qShDAgaJpZM4IkuA9
.

Saya sangat setuju bahwa pola yang dijelaskan cukup umum. Memiliki cara untuk mengekspresikannya tanpa tindakan masuk akal.

Apa yang saya tidak begitu yakin tentang solusi yang diusulkan (operator ^ ). Menggunakan karakter khusus yang maknanya tidak langsung jelas selalu bermasalah dan menambah kurva belajar. Mungkin juga karakter tersebut akan lebih baik digunakan untuk tujuan lain. Last but not least, saya tidak suka ide menempatkan hal-hal yang tidak secara langsung mempengaruhi parsing ke dalam ekspresi banyak. Orang dapat berargumen bahwa sudah ada satu contoh dari ini — operator $ — dan saya setuju. Tapi saya tidak yakin apakah penambahan $ bukan kesalahan (kecil). Jika demikian, saya ingin menghindari membuatnya lagi.

Saya akan memikirkan ini lebih dalam setelah 1.0.0.

Beberapa bahan untuk dipikirkan: karena ^ dan ekspresi berlabel semacam bertabrakan ( @grrrwaaa menyarankan untuk mengabaikan ^ ), bagaimana kalau alih-alih menandai hasilnya, seseorang dapat menandai ekspresi _ignored_, misalnya (saran sintaks!) dengan memberikan label kosong:

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = :WhiteSpace? Identifier :WhiteSpace?

Di sana, tidak ada sintaks baru (kami sudah memiliki : ), hanya sedikit ekstensi pada semantik:

  • izinkan label kosong (sebut saja ekspresi "anonim" ini?)
  • jika hanya ada satu tangkapan non-anonim, jangan buat larik kecocokan ekspresi, alih-alih kembalikan satu-satunya kecocokan

Dalam hal ini lebih konsisten akan menandai dengan "label" kosong ekspresi yang perlu dikembalikan sebagai hasilnya. Omong-omong, itu bukan untuk mematahkan semantik yang ada: labelnya ada, tetapi tidak disebutkan namanya; saat label diperkenalkan untuk akses ke hasil, cukup logis bahwa label tanpa nama secara otomatis menjadi hasil. Keberadaan label otomatis dan beton secara bersamaan harus dilarang. Jika hanya ada satu label otomatis, maka hasil tunggal, tetapi bukan larik dengan satu elemen harus dikembalikan karena perilaku seperti itu lebih dituntut.

@Mingun

Mengapa tidak mengembalikan label saja?
start = "{" :expr "}" // return expr
start = "{" label:expr "}" // return label
Saya pikir masuk akal jika Anda "memberi label" sesuatu maka Anda ingin melakukan sesuatu dengannya (misalnya mengembalikannya).

Di sisi lain, mengapa aturan seperti start = ex:expr :expr harus memunculkan kesalahan?
Mungkin itu harus melakukan sesuatu yang mirip dengan variabel argumen fungsi javascript? Misalnya start = ex:expr :expr harus mengembalikan [ex, expr] . Ketika Anda memiliki tindakan, harus ada variabel berlabel & arguments ( start = ex:expr :expr { return [ex, arguments[0], ex] } )

@alanmimms Saya suka ide ini. Kita tidak perlu membuat nama (variabel/label) hanya untuk mengembalikan nilai sederhana.
Saya pikir label tanpa nama ( :expr ) akan lebih baik daripada ^expr

Mengapa tidak mengembalikan label saja?

@nedzadarek karena jika Anda memberi nama untuk ekspresi, kemungkinan besar Anda tidak akan menggunakannya dalam ekspresi yang tidak sepele. Setidaknya, nama itu penting bagi Anda, jika tidak, Anda tidak akan memberikannya, sungguh? Juga, mencampur label bernama dan tanpa nama lebih mungkin merupakan kesalahan daripada tindakan sadar, jadi akan lebih aman jika dilarang. Jika Anda memberi satu nama mengapa tidak memberikan yang lain?

Sayangnya, perlu untuk mengenali bahwa label otomatis dalam tampilan apa yang ditawarkan oleh @opatut , tidak mungkin diterapkan karena menciptakan ambiguitas dalam tata bahasa. Contoh dasar:

start = a :b;// `a` - it is rule reference or label?
a = .;
b = .;

Jadi, untuk tujuan ini perlu memilih karakter lain. Saat ini ada pilihan dari: ~ , (backslash) , @ , # , % , ^ , - , | , \ dan , .


Solusi lain -- perkenalkan beberapa tindakan semu -- pintasan untuk membuat fungsi sederhana untuk pengembalian, misalnya, {=>[]} dapat berarti _"mengumpulkan hasil berlabel dari urutan dan mengembalikannya ke dalam larik"_ , dan {=>{}} -- sama, tetapi untuk mengembalikan objek, dengan kunci yang sama dengan nama label. Tetapi implementasi dari perilaku ini tidak memerlukan ekstensi tata bahasa dan dapat diwujudkan dengan plug-in. Saya bahkan akan mengatakan bahwa lebih disukai memiliki implementasi seperti itu dengan plug-in:

start1 = a:'a' b c d:. {=>[]};// returns ['a', <d value>]
start2 = a:'a' b c d:. {=>{}};// returns { a: 'a', d: <d value> }

@Mingun

karena jika Anda memberi nama untuk ekspresi, kemungkinan besar Anda tidak akan menggunakannya dalam ekspresi yang tidak sepele. Setidaknya, nama itu penting bagi Anda, jika tidak, Anda tidak akan memberikannya, sungguh?

Ya, namanya penting => Saya ingin menggunakannya => Saya ingin mengembalikannya.
Apa masalahnya dengan ekspresi non-sepele?

Sayangnya, perlu untuk mengenali bahwa label otomatis dalam tampilan apa yang ditawarkan oleh @opatut , tidak mungkin diterapkan karena menciptakan ambiguitas dalam tata bahasa. Contoh dasar:

Ya.
Saya kira ::expression membingungkan juga? @dmajda

Ditutup sebagai duplikat #235

Sunting: Menambahkan catatan ke komentar OP di # 235 yang merujuk masalah ini

Apakah halaman ini membantu?
0 / 5 - 0 peringkat