Pegjs: Singkatan untuk Tindakan Semantik

Dibuat pada 10 Sep 2018  ·  13Komentar  ·  Sumber: pegjs/pegjs

Akan lebih baik untuk menambahkan singkatan untuk tindakan semantik.

Katakanlah, alih-alih menulis { return value } , kita menulis, misalnya { extract } yang didefinisikan dalam penginisialisasi.

Sebagai contoh:

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item { extract } )* _ ')' { concat }

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply { extract } )* _ ')' { toAddExpr }

Pertama, ini akan membuat kita dapat menggunakan kembali fungsi... dengan cara yang lebih baik :smile:
Kedua, ini akan membuat tata bahasa kita sedikit lebih mudah dibaca.

Saya percaya itu juga akan lebih berguna ketika ekspresi yang terkandung dalam singkatan tindakan adalah ekspresi anggota { foo.bar.baz } bukan hanya pengenal { foo } . Sehingga penulis tata bahasa dapat mengatur fungsinya di dalam suatu objek atau bahkan modul.

discussion feature

Komentar yang paling membantu

Sebenarnya, saya telah berpikir, perubahan ini mungkin berhasil:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Cara ini masih perlu mengintegrasikan beberapa hal seperti ekspresi utama ECMAScript (angka, boolean, array, dll) untuk digunakan sebagai argumen, jadi perlu hati-hati mencari tahu apa yang harus ditambahkan.


menyeimbangkan kurung dan kawat gigi

Ini tidak akan diperbaiki sampai pengurai JavaScript yang tepat dibangun ke dalam pengurai PEG.js, tetapi sejujurnya saya sedikit ragu tentang ini karena ada beberapa proyek plugin yang menghasilkan pengurai dalam bahasa lain (C, PHP, TypeScript , dll), dan saya juga sedang mengerjakan bahasa komputer yang saya harap suatu hari dapat menghasilkan parser.


Bersamaan dengan _PEG.js v0.12_, saya akan mengerjakan OpenPEG , yang akan menawarkan paket NPM yang pada dasarnya adalah versi PEG.js yang dipreteli tanpa melibatkan pembuatan JavaScript dan parser, tetapi fitur yang cukup sehingga proyek berbasis JavaScript seperti PEG.js dapat menggunakannya sebagai backend. Ketika _v0.12_ keluar, saya akan mencoba dan memastikan setiap proyek plugin yang menghasilkan parser khusus diberitahu tentang OpenPEG, dan sebelum v1 menerapkan parser ECMAScript 2015 lengkap ke dalam parser tata bahasa PEG.js.

Semua 13 komentar

Ide yang menarik, tetapi saya pribadi tidak berpikir itu akan menjadi cara yang lebih jelas, karena tidak jelas argumen mana yang diteruskan ke fungsi. Juga, jika Anda harus melewati parameter "khusus" - Anda harus mencampurnya dengan panggilan fungsi biasa, sehingga tidak akan terlihat sebersih dalam kasus yang lebih sederhana.

Seseorang di #235 menyarankan sintaks => untuk mengikuti fungsi panah, yang menurut saya cukup bersih dan ringkas.

  = '(' expr:some_expression ')' => expr
  ;

Saya condong memilih salah satu dari yang berikut untuk sintaks steno:

  • => expr; _(membutuhkan dukungan untuk sintaks)_
  • { => expr } _(dapat digunakan sekarang, tetapi perlu dibuka)_
  • { > expr } _(membutuhkan dukungan untuk sintaks)_

Belum diputuskan, jadi terbuka untuk diskusi.

Adapun apa yang diinginkan OP, akan lebih baik untuk mengimplementasikan plugin (setelah atau sebelum sintaks singkatan diputuskan) yang menggunakan Acorn atau @babel/parser untuk membuka pengidentifikasi atau ekspresi anggota, mengubahnya menjadi ekspresi panggilan sambil menambahkan label sebagai argumen dan kembalikan kode yang dihasilkan.

=> expr;

Terbaik menurut saya.

{ => expr }

Konflik dengan sintaksis Javascript IMO. Karena berada di dalam { } Anda akan mengharapkannya menjadi fungsi panah penuh ( () => ).

{ > expr}

Agak ortogonal dengan sintaks lain baik dalam PegJS atau Javascript, tidak langsung membaca "ini mengembalikan nilai, singkatan" IMO - terutama karena itu dalam kurung kurawal, saya pikir. Argumen yang sama dengan {=> expr} , Anda mengharapkan Javascript ada di sana.


Lebih lanjut, menambahkan sintaks non-JS di {} adalah masalah untuk penyorot sintaks, linter, dll. Saya sarankan untuk tidak melakukannya.

Jika saya dapat menyarankan opsi lain, mungkin > dengan sendirinya (tidak di dalam blok predikat). Itu membantu menjaga hal-hal tetap selaras saat Anda mengatur aturan secara vertikal:

    = foo:bar qux:(' '+ @qix)+
    > {foo, qux}
    ;

serta sebaris

some_rule = foo:bar qux:(' '+ @qix)+ > {foo, qux};

Mengapa titik koma diperlukan untuk '=>'? Saya ingin mengembalikan nilai dalam kode bersarang alih-alih menggunakan buildList() misalnya:

  = "(" _ head:Expression _ tail:("," _ expr:Expression => expr)* ")" {
      return [head, ...tail]
    }

Saya menemukan ini lebih bersih daripada menggunakan indeks ajaib (di bawah). Pilihan lain adalah kemampuan untuk merujuk ke label bersarang. misalnya ("," _ tail:Expression)* ")"

  = "(" _ head:Expression _ tail:("," _ Expression)* ")" {
      return buildList(head, tail, 2)
    }

Saya sedang melihat parser.pegjs, dan saya melihat di sekitar baris 434 ada CodeBlock. Apa yang perlu dilakukan untuk mencobanya? Kode aturan hanya membaca SourceCharacter, yang hanya '.'

CodeBlock "code block"
  = "=>" __ <strong i="13">@Code</strong> // this?
  / "{" <strong i="14">@Code</strong> "}"

@mikeaustin Ya, itu benar, tetapi tidak ada cara untuk mengetahui di mana harus mengakhiri urutan ini, jadi akan mengkonsumsi semuanya setelah =>

Mungkin "Kode" bisa sedikit lebih pintar, menyeimbangkan tanda kurung dan kawat gigi, dan menangani LineTerminator? Itu tidak perlu tahu tentang JavaScript lengkap, tetapi itu mungkin lebih sulit daripada kedengarannya.

Sebenarnya, saya telah berpikir, perubahan ini mungkin berhasil:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Cara ini masih perlu mengintegrasikan beberapa hal seperti ekspresi utama ECMAScript (angka, boolean, array, dll) untuk digunakan sebagai argumen, jadi perlu hati-hati mencari tahu apa yang harus ditambahkan.


menyeimbangkan kurung dan kawat gigi

Ini tidak akan diperbaiki sampai pengurai JavaScript yang tepat dibangun ke dalam pengurai PEG.js, tetapi sejujurnya saya sedikit ragu tentang ini karena ada beberapa proyek plugin yang menghasilkan pengurai dalam bahasa lain (C, PHP, TypeScript , dll), dan saya juga sedang mengerjakan bahasa komputer yang saya harap suatu hari dapat menghasilkan parser.


Bersamaan dengan _PEG.js v0.12_, saya akan mengerjakan OpenPEG , yang akan menawarkan paket NPM yang pada dasarnya adalah versi PEG.js yang dipreteli tanpa melibatkan pembuatan JavaScript dan parser, tetapi fitur yang cukup sehingga proyek berbasis JavaScript seperti PEG.js dapat menggunakannya sebagai backend. Ketika _v0.12_ keluar, saya akan mencoba dan memastikan setiap proyek plugin yang menghasilkan parser khusus diberitahu tentang OpenPEG, dan sebelum v1 menerapkan parser ECMAScript 2015 lengkap ke dalam parser tata bahasa PEG.js.

FWIW, saya sudah mulai menggunakan literal template untuk ini. Ini juga membantu saya dengan penyorotan sintaks JS oleh editor teks saya ...

exports = module.exports = functionBodies`${grammarScript}
...
objectText =
    head:word
    rest:(_txt_ word)*
    ${f=>{
        return new Txt(rest.reduce((a,b)=>([...a,...b]),[head]))
        }}
word = ch:(wordCharacter/escapedCharacter)+ ${chJoin}
...
`
function functionBodies(glue, ...fns){
    return glue.map( (str,i) => str + (fns[i]||'').toString().replace(/^[^{]*/,'').replace(/[^}]*$/, '') ).join('')
    }

function chJoin(ch){return ch.join('')}

Bagaimana dengan menggunakan operator pipa yang diusulkan (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator)? Karena, pada dasarnya, Anda meminta untuk menyalurkan data?

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item |> extract )* _ ')' |> concat

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply |> extract  )* _ ')' |> toAddExpr

Semua ini tidak boleh terjadi. Seharusnya tidak ada sintaks pendek.

Semua ini tidak diperlukan jika kita hanya mengurai panah secara normal, alih-alih mencoba menggesernya ke samping.

Meskipun ini adalah ide yang bagus, ini membuat ambiguitas tata bahasa yang luas versus JavaScript. Siapa pun yang mem-parsing JS dan mengingat betapa buruknya with tahu bahwa ini pada dasarnya akan membunuh parser.

Alih-alih mencoba membuat hal-hal baru yang mewah, kita sebaiknya mendukung Javascript. Fungsi panah lebih tua dari ES6 dan ES6 dari 2015. Ini diselesaikan enam tahun lalu. Tidak ada penemuan yang harus terjadi di sini.

Operator pipa sangat cacat dan mungkin tidak akan benar-benar membuatnya menjadi Javascript, dan baik bahasa asalnya (F#) dan bahasa yang mempopulerkannya (Elixir) mundur darinya. Selain itu, ini tidak perpipaan dalam arti apapun.

Alasan PEG begitu sukses adalah karena minimal, dan tetap dekat dengan bahasa, memungkinkannya menjadi cepat, kecil, dan dapat diprediksi.

Fungsi panah lebih tua dari ES6 dan ES6 dari 2015. Ini diselesaikan enam tahun lalu. Tidak ada penemuan yang harus terjadi di sini.

Uh. Itu berita bagi saya. Ingin memperluas?

Alasan PEG begitu sukses adalah karena minimal, dan tetap dekat dengan bahasa, memungkinkannya menjadi cepat, kecil, dan dapat diprediksi.

Alasan PEG (sebagai konsep, bukan perpustakaan ini) berhasil adalah karena kemampuannya untuk mewakili tata bahasa yang kompleks (rekursif, dll.) dengan cara yang sederhana. Packrat tidak ditemukan dengan perpustakaan ini; itu bukan sintaks. Ini adalah sebuah algoritma.

Fungsi panah lebih tua dari ES6 dan ES6 dari 2015. Ini diselesaikan enam tahun lalu. Tidak ada penemuan yang harus terjadi di sini.

Uh. Itu berita bagi saya. Ingin memperluas?

Saya tidak benar-benar tahu apa yang Anda tanyakan.

Fungsi panah lebih tua dari ES6. Ini adalah pertarungan terbesar kedua di ES6, yang menggelincirkan ES4, dan yang menggelincirkan ES5+. Semua orang telah meminta mereka, pada saat itu, sejak pertengahan 90-an, karena mereka sebenarnya sudah ada di E4X, dan diambil karena Google dan Apple mengecam Hixie tentang Microsoft yang pernah menciptakan sesuatu.

Anda sekarang tahu E4X sebagai React, dan mengira Facebook yang menciptakannya. Facebook mengira mereka merobek Hyperscript. Orang Hyperscript jelas bahwa dia baru saja mengimplementasikan kembali hal yang berguna dari IE lama.

Mereka akan ditinggalkan sepenuhnya dari ES6, seperti string template, tetapi kemudian Coffeescript datang dan memberikan komunitas JS keduanya, dan kemudian komunitas JS berteriak sampai orang-orang ECMA mengalah. Hanya butuh 18 bulan

Fungsi panah melakukan semua yang perlu terjadi di sini. Anda bahkan tampaknya menjadi orang yang mengangkat mereka di utas ini, pada tahun 2018, yang membuat ketidaksetujuan Anda cukup mengejutkan; Saya mencoba untuk mendukung Anda.

Lebih penting lagi bagi saya, jika dilakukan dengan fungsi panah, tidak ada yang ditambahkan.

Perbedaan Peg dari JS benar-benar minimal. Mendukung ini dengan hanya melakukan hal-hal ES6 berarti daftar itu tidak berubah.

Itu sangat berharga.


Alasan PEG (sebagai konsep, bukan perpustakaan ini) berhasil adalah karena kemampuannya untuk mewakili tata bahasa yang kompleks (rekursif, dll.) dengan cara yang sederhana.

Saya tidak setuju. Banyak pengurai melakukan pekerjaan yang jauh lebih baik dalam hal ini, dan bahkan tidak sedikit populer, bahkan dengan orang-orang yang mengetahuinya (seperti Earley.)

Penjelasan tradisional adalah kombinasi dari kualitas dan kecepatan pesan kesalahan, tetapi saya juga tidak setuju dengan itu, karena banyak parser memiliki pesan kesalahan yang lebih baik lebih cepat (sekali lagi, seperti Earley,) dan bahkan tidak sedikit populer, bahkan dengan orang-orang. siapa yang tahu tentang mereka?

Juga, perhatikan bahwa PEG memiliki tiga plafon kompleksitas yang serius.

Satu, apa pun yang ingin Anda masukkan melalui tata bahasa pasak harus memiliki ekspresi kombinatorik yang tidak membanjiri cache dan hasil evaluasi mesin lokal (dengan contoh #623)

Dua, banyak pekerjaan umum, seperti parsing BNF, sering kali sangat sulit untuk dipatok (dengan contoh #489)

Tiga, perlu dicatat bahwa setiap perpustakaan JS PEG lainnya, bahkan yang jauh lebih kuat, telah gagal. Saya mencoba untuk beralih, dan telah kembali, berkali-kali. Secara khusus, saya telah mencoba untuk beralih ke canopy beberapa kali, karena memungkinkan saya untuk menargetkan c , ruby , dan python sebagai tambahan ke javascript

Memang, yang bisa saya bicarakan hanyalah dua lusin orang yang saya kenal yang menggunakannya. Dan saya bisa, karena saya bertanya beberapa hari yang lalu, ketika saya menyadari non-pengelola baru membuang perangkat lunak dan menggantinya dengan sesuatu yang dia buat dari awal, setelah bertahun-tahun tidak ada perubahan yang dipublikasikan

Tetapi masing-masing dari mereka mengatakan kepada saya bahwa mereka membutuhkan parser yang tidak memiliki banyak overhead konseptual asli, atau bahwa mereka membutuhkan sesuatu yang cepat dan kecil yang perilakunya dapat diandalkan

0.11 yang belum dirilis berperilaku sangat berbeda dalam node vs chrome, dan node terbuat dari chrome. Coba tulis beberapa pengujian properti terhadapnya. Sejujurnya ini agak menakutkan.

.

Packrat tidak ditemukan dengan perpustakaan ini; itu bukan sintaks. Ini adalah sebuah algoritma.

Saya tidak mengatakan apa-apa tentang Packrat, teman. Saya tidak yakin apa yang Anda coba perbaiki.

Namun, penguraian Packrat bukanlah sebuah algoritma, untuk alasan yang sama bahwa sortir bukanlah sebuah algoritma. Parsing Packrat adalah tugas, dan ada banyak cara untuk melakukannya.

Memang, sebagian besar buku intro haskell membuat Anda melakukan tiga atau empat parser packrat yang berbeda, karena itu adalah cara yang bagus untuk benar-benar terpaku pada masalah kinerja pendekatan haskell ke monad, dan mereka ingin menunjukkan kepada Anda bagaimana mengubah pendekatan untuk menulis packrats (yaitu, mengubah algoritma) menghasilkan hasil yang lebih baik.

.

Harap pertimbangkan kembali bahwa jempol ke bawah. Perpustakaan ini telah mati selama tiga tahun, dan saya ingin menghidupkannya kembali sekarang.

Sebagian alasan perpustakaan mati adalah karena orang-orang terus mencoba menciptakan fitur-fitur greenfield, alih-alih melakukan perawatan sederhana, seperti menambahkan fungsi modul es() yang telah ada di dev selama dua tahun

Saya harus memodifikasi parser PEG saya secara manual dengan memotong garis dan menstaples javascript tulisan tangan ke ujungnya

Mata berbintang akan menutup sebentar, dan beberapa siku berminyak praktis harus dimulai. PEG satu-satunya perpustakaan NPM utama yang pernah saya lihat dengan penggunaan yang menurun. Mengingat bahwa saya tidak mengetahui pengganti yang masuk akal, itu aneh dan membingungkan bagi saya.

image

Saya memiliki perbaikan bug yang ingin saya sumbangkan sekarang, tetapi saya tidak bisa, karena

  1. 0.10 belum dipublikasikan sejak dmajda pergi,
  2. 0.11 berumur tiga tahun, belum pernah dipublikasikan, dan diumumkan sebulan yang lalu tidak akan pernah dipublikasikan, dan
  3. Penggantinya, 0.12 , sama sekali bukan pasak, tetapi sesuatu yang ditulis orang lain dari awal dalam bahasa pemrograman yang berbeda, dan tidak seorang pun dari kita dapat melihatnya

Saya tahu itu tidak sopan, tetapi kita harus menghadapi bahwa perpustakaan ini sedang dibunuh

Saatnya menghadapi bahwa kita harus menerima proses pengembangan normal jika perpustakaan ini akan melihat pembaruan lagi. Ini tahun 2020. Kami belum melihat apa-apa sejak 2017.

Tidak, cabang dev tidak dihitung. Dan pengelola baru harus membuka kembali banyak masalah, karena 0.11 tidak cukup berkualitas, dan memulai kembali dari 10 jauh lebih sedikit pekerjaan daripada memperbaiki 11

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

futagoza picture futagoza  ·  6Komentar

richb-hanover picture richb-hanover  ·  7Komentar

StoneCypher picture StoneCypher  ·  8Komentar

StoneCypher picture StoneCypher  ·  6Komentar

mikeaustin picture mikeaustin  ·  7Komentar