Saya telah mengembangkan parser persamaan menggunakan algoritma tumpukan sederhana yang akan menangani operator biner (+, -, |, &, *, /, dll), operator unary (!), Dan tanda kurung.
Menggunakan metode ini, bagaimanapun, membuat saya memiliki semua yang memiliki prioritas yang sama - itu dievaluasi dari kiri ke kanan terlepas dari operatornya, meskipun prioritas dapat diterapkan menggunakan tanda kurung.
Jadi saat ini "1 + 11 * 5" menghasilkan 60, bukan 56 seperti yang diharapkan.
Meskipun ini cocok untuk proyek saat ini, saya ingin memiliki rutinitas tujuan umum yang dapat saya gunakan untuk proyek selanjutnya.
Diedit untuk kejelasan:
Apa algoritme yang baik untuk mengurai persamaan dengan prioritas?
Saya tertarik pada sesuatu yang sederhana untuk diterapkan dan memahami bahwa saya dapat membuat kode sendiri untuk menghindari masalah lisensi dengan kode yang tersedia.
Tatabahasa:
Saya tidak mengerti pertanyaan tata bahasa - saya telah menulis ini dengan tangan. Cukup sederhana sehingga saya tidak melihat perlunya YACC atau Bison. Saya hanya perlu menghitung string dengan persamaan seperti "2 + 3 * (42/13)".
Bahasa:
Saya melakukan ini di C, tetapi saya tertarik pada algoritme, bukan solusi khusus bahasa. C cukup rendah sehingga mudah untuk dikonversi ke bahasa lain jika diperlukan.
Contoh Kode
Saya memposting kode tes untuk pengurai ekspresi sederhana yang saya bicarakan di atas. Persyaratan proyek diubah dan jadi saya tidak perlu mengoptimalkan kode untuk kinerja atau ruang karena tidak dimasukkan ke dalam proyek. Ini dalam bentuk verbose asli, dan harus mudah dimengerti. Jika saya melakukan sesuatu lebih jauh dengan itu dalam hal prioritas operator, saya mungkin akan memilih peretasan makro karena itu cocok dengan program lainnya dalam kesederhanaan. Jika saya pernah menggunakan ini dalam proyek nyata, saya akan menggunakan parser yang lebih kompak / cepat.
Pertanyaan terkait
-Adam
Jawaban:
Cara yang sulit
Anda menginginkan parser keturunan rekursif .
Untuk mendapatkan prioritas, Anda perlu berpikir secara rekursif, misalnya, menggunakan string sampel Anda,
untuk melakukan ini secara manual, Anda harus membaca
1
, lalu melihat plus dan memulai "sesi" penguraian rekursif baru yang dimulai dengan11
... dan pastikan untuk mengurai11 * 5
ke dalam faktornya sendiri, menghasilkan pohon parse dengan1 + (11 * 5)
.Ini semua terasa sangat menyakitkan bahkan untuk mencoba menjelaskan, terutama dengan ketidakberdayaan yang ditambahkan dari C. Lihat, setelah mengurai 11, jika * sebenarnya adalah +, Anda harus mengabaikan upaya membuat istilah dan sebagai gantinya mengurai
11
dirinya sebagai faktor. Kepalaku sudah meledak. Itu mungkin dengan strategi rekursif yang layak, tetapi ada cara yang lebih baik ...Cara yang mudah (benar)
Jika Anda menggunakan alat GPL seperti Bison, Anda mungkin tidak perlu khawatir tentang masalah perizinan karena kode C yang dihasilkan oleh bison tidak tercakup oleh GPL (IANAL tetapi saya cukup yakin alat GPL tidak memaksa GPL aktif kode / binari yang dihasilkan; misalnya Apple mengkompilasi kode seperti say, Aperture dengan GCC dan mereka menjualnya tanpa harus GPL kode tersebut).
Unduh Bison (atau yang setara, ANTLR, dll.).
Biasanya ada beberapa kode contoh yang bisa Anda gunakan untuk menjalankan bison dan mendapatkan kode C yang Anda inginkan yang mendemonstrasikan empat fungsi kalkulator ini:
http://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html
Lihatlah kode yang dihasilkan, dan lihat bahwa ini tidak semudah kedengarannya. Juga, keuntungan menggunakan alat seperti Bison adalah 1) Anda belajar sesuatu (terutama jika Anda membaca buku Naga dan mempelajari tata bahasa), 2) Anda menghindari NIH mencoba menemukan kembali roda. Dengan alat pembuat parser yang sebenarnya, Anda sebenarnya memiliki harapan untuk meningkatkannya nanti, menunjukkan kepada orang lain bahwa Anda tahu bahwa parser adalah domain alat parsing.
Memperbarui:
Orang-orang di sini telah memberikan banyak nasihat yang masuk akal. Satu-satunya peringatan saya agar tidak melewatkan alat parsing atau hanya menggunakan algoritma Shunting Yard atau parser rekursif yang digulung tangan adalah bahwa bahasa mainan kecil 1 suatu hari nanti dapat berubah menjadi bahasa aktual besar dengan fungsi (sin, cos, log) dan variabel, kondisi dan untuk loop.
Flex / Bison mungkin berlebihan untuk penerjemah kecil dan sederhana, tetapi parser + evaluator dapat menyebabkan masalah saat perubahan perlu dilakukan atau fitur perlu ditambahkan. Situasi Anda akan berbeda dan Anda perlu menggunakan penilaian Anda; hanya saja, jangan menghukum orang lain atas dosa-dosa Anda [2] dan membangun alat yang kurang dari cukup.
Alat favorit saya untuk parsing
Alat terbaik di dunia untuk pekerjaan itu adalah pustaka Parsec (untuk pengurai yang layak rekursif) yang hadir dengan bahasa pemrograman Haskell. Ini terlihat sangat mirip dengan BNF , atau seperti alat khusus atau bahasa khusus domain untuk penguraian (kode contoh [3]), tetapi sebenarnya ini hanya pustaka biasa di Haskell, yang berarti bahwa ia mengkompilasi dalam langkah pembuatan yang sama dengan yang lain dari kode Haskell Anda, dan Anda dapat menulis kode Haskell arbitrer dan memanggilnya dalam parser Anda, dan Anda dapat mencampur dan mencocokkan semua pustaka lain dalam kode yang sama . (Ngomong-ngomong, menyematkan bahasa penguraian seperti ini dalam bahasa selain Haskell menghasilkan banyak sintaksis. Saya melakukan ini di C # dan berfungsi dengan cukup baik tetapi tidak begitu cantik dan ringkas.)
Catatan:
1 Richard Stallman berkata, dalam Why you should not use Tcl
[2] Ya, saya selamanya takut menggunakan "bahasa" itu.
Juga perhatikan bahwa ketika saya mengirimkan entri ini, pratinjau benar, tetapi pengurai SO kurang dari cukup memakan tag jangkar dekat saya pada paragraf pertama , membuktikan bahwa parser bukanlah sesuatu yang bisa dianggap enteng karena jika Anda menggunakan regex dan satu kali meretas Anda mungkin akan mendapatkan kesalahan kecil dan halus .
[3] Cuplikan pengurai Haskell menggunakan Parsec: kalkulator empat fungsi yang dilengkapi dengan eksponen, tanda kurung, spasi untuk perkalian, dan konstanta (seperti pi dan e).
sumber
The algoritma halaman shunting adalah alat yang tepat untuk ini. Wikipedia benar-benar membingungkan tentang ini, tetapi pada dasarnya algoritme berfungsi seperti ini:
Katakanlah, Anda ingin mengevaluasi 1 + 2 * 3 + 4. Secara intuitif, Anda "tahu" bahwa Anda harus melakukan 2 * 3 terlebih dahulu, tetapi bagaimana Anda mendapatkan hasil ini? Kuncinya adalah menyadari bahwa saat Anda memindai string dari kiri ke kanan, Anda akan mengevaluasi operator saat operator yang mengikutinya memiliki prioritas yang lebih rendah (atau sama dengan). Dalam konteks contoh, inilah yang ingin Anda lakukan:
Bagaimana Anda menerapkan ini?
Anda ingin memiliki dua tumpukan, satu untuk nomor, dan satu lagi untuk operator. Anda mendorong angka ke tumpukan setiap saat. Anda membandingkan setiap operator baru dengan yang ada di bagian atas tumpukan, jika yang di atas tumpukan memiliki prioritas lebih tinggi, Anda mengeluarkannya dari tumpukan operator, mengeluarkan operan dari tumpukan nomor, menerapkan operator dan mendorong hasilnya ke tumpukan nomor. Sekarang Anda ulangi perbandingan dengan operator tumpukan atas.
Kembali ke contoh, ini berfungsi seperti ini:
N = [] Operasi = []
*
. N = [1 2], Ops = [+ *]*
3, dan dorong hasilnya ke N. N = [1 6], Ops = [+]+
dibiarkan asosiatif, jadi Anda ingin menghapus 1, 6 juga dan menjalankan +. N = [7], Ops = [].Nah, itu tidak terlalu sulit, bukan? Dan itu tidak membuat permintaan ke tata bahasa atau generator parser.
sumber
http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
Penjelasan yang sangat bagus tentang pendekatan yang berbeda:
Ditulis dengan bahasa yang sederhana dan pseudo-code.
Saya suka 'pendakian prioritas'.
sumber
Ada artikel bagus di sini tentang menggabungkan parser keturunan rekursif sederhana dengan penguraian prioritas operator. Jika Anda baru-baru ini menulis parser, bacanya harus sangat menarik dan instruktif.
sumber
Dahulu kala, saya membuat algoritme penguraian sendiri, yang tidak dapat saya temukan di buku mana pun tentang penguraian (seperti Buku Naga). Melihat petunjuk ke algoritma Shunting Yard, saya melihat kemiripannya.
Sekitar 2 tahun yang lalu, saya membuat postingan tentang itu, lengkap dengan source code Perl, di http://www.perlmonks.org/?node_id=554516 . Sangat mudah untuk melakukan port ke bahasa lain: implementasi pertama yang saya lakukan adalah di assembler Z80.
Ini ideal untuk penghitungan langsung dengan angka, tetapi Anda bisa menggunakannya untuk menghasilkan pohon parse jika perlu.
Perbarui Karena lebih banyak orang dapat membaca (atau menjalankan) Javascript, saya telah menerapkan ulang parser saya di Javascript, setelah kode diatur ulang. Keseluruhan parser berada di bawah 5k kode Javascript (sekitar 100 baris untuk parser, 15 baris untuk fungsi pembungkus) termasuk pelaporan kesalahan, dan komentar.
Anda dapat menemukan demo langsung di http://users.telenet.be/bartl/expressionParser/expressionParser.html .
sumber
Akan membantu jika Anda dapat mendeskripsikan tata bahasa yang saat ini Anda gunakan untuk mengurai. Sepertinya masalahnya mungkin ada di sana!
Edit:
Fakta bahwa Anda tidak memahami pertanyaan tata bahasa dan bahwa 'Anda telah menulis ini dengan tangan' sangat mungkin menjelaskan mengapa Anda mengalami masalah dengan ekspresi bentuk '1 + 11 * 5' (yaitu, dengan prioritas operator) . Googling untuk 'tata bahasa untuk ekspresi aritmatika', misalnya, akan menghasilkan beberapa petunjuk yang bagus. Tata bahasa seperti itu tidak perlu rumit:
akan melakukan trik tersebut misalnya, dan dapat ditambah secara sepele untuk menangani beberapa ekspresi yang lebih rumit (termasuk fungsi misalnya, atau pangkat, ...).
Saya sarankan Anda melihat utas ini , misalnya.
Hampir semua pengantar tata bahasa / parsing memperlakukan ekspresi aritmatika sebagai contoh.
Perhatikan bahwa menggunakan tata bahasa sama sekali tidak berarti menggunakan alat tertentu ( a la Yacc, Bison, ...). Memang, Anda pasti sudah menggunakan tata bahasa berikut:
(atau sejenisnya) tanpa menyadarinya!
sumber
Pernahkah Anda berpikir untuk menggunakan Boost Spirit ? Ini memungkinkan Anda untuk menulis tata bahasa seperti EBNF di C ++ seperti ini:
sumber
Saat Anda mengajukan pertanyaan, tidak perlu rekursi apa pun. Jawabannya adalah tiga hal: Notasi Postfix ditambah algoritma Shunting Yard ditambah evaluasi ekspresi Postfix:
1). Notasi postfix = diciptakan untuk menghilangkan kebutuhan akan spesifikasi prioritas eksplisit. Baca lebih lanjut di internet tetapi inilah intinya: ekspresi infix (1 + 2) * 3 sementara mudah bagi manusia untuk membaca dan memproses tidak terlalu efisien untuk komputasi melalui mesin. Apa yang? Aturan sederhana yang mengatakan "tulis ulang ekspresi dengan meng-cache di awal, lalu selalu proses dari kiri ke kanan". Jadi infix (1 + 2) * 3 menjadi postfix 12 + 3 *. POST karena operator ditempatkan selalu SETELAH operan.
2). Mengevaluasi ekspresi postfix. Mudah. Baca angka dari string postfix. Dorong mereka di atas tumpukan sampai seorang operator terlihat. Periksa jenis operator - unary? biner? tersier? Keluarkan operan dari tumpukan sebanyak yang diperlukan untuk mengevaluasi operator ini. Evaluasi. Dorong kembali hasil ke tumpukan! Dan kamu hampir selesai. Terus lakukan hingga tumpukan hanya memiliki satu entri = nilai yang Anda cari.
Ayo lakukan (1 + 2) * 3 yang di postfix adalah "12 + 3 *". Baca angka pertama = 1. Dorong di atas tumpukan. Baca selanjutnya. Nomor = 2. Dorong di atas tumpukan. Baca selanjutnya. Operator. Yang mana? +. Jenis apa? Biner = membutuhkan dua operan. Pop stack dua kali = argright adalah 2 dan argleft adalah 1. 1 + 2 adalah 3. Dorong 3 kembali ke stack. Baca selanjutnya dari string postfix. Ini angka. 3. Dorong. Baca selanjutnya. Operator. Yang mana? *. Jenis apa? Biner = membutuhkan dua angka -> pop stack dua kali. Pertama masuk ke argright, kedua kali ke argleft. Evaluasi operasi - 3 kali 3 adalah 9. Dorong 9 pada tumpukan. Baca karakter postfix selanjutnya. Nol. Akhir masukan. Pop stack onec = itulah jawaban Anda.
3). Shunting Yard digunakan untuk mengubah ekspresi infix manusia (mudah) menjadi ekspresi postfix (juga manusia mudah dibaca setelah beberapa latihan). Mudah dikodekan secara manual. Lihat komentar di atas dan net.
sumber
Apakah ada bahasa yang ingin Anda gunakan? ANTLR akan membiarkan Anda melakukan ini dari perspektif Java. Adrian Kuhn memiliki sangat baik Langgan tentang cara menulis tata bahasa dieksekusi di Ruby; sebenarnya, contohnya hampir persis dengan contoh ekspresi aritmatika Anda.
sumber
Itu tergantung pada seberapa "umum" yang Anda inginkan.
Jika Anda ingin benar-benar umum seperti dapat mengurai fungsi matematika serta sin (4 + 5) * cos (7 ^ 3), Anda mungkin memerlukan pohon parse.
Di mana, menurut saya implementasi lengkap tidak layak untuk ditempelkan di sini. Saya menyarankan agar Anda melihat salah satu " Buku Naga " yang terkenal .
Tetapi jika Anda hanya menginginkan dukungan prioritas , maka Anda dapat melakukannya dengan terlebih dahulu mengubah ekspresi menjadi bentuk postfix di mana algoritme yang dapat Anda salin dan tempel harus tersedia dari google atau saya rasa Anda dapat mengkodekannya sendiri dengan biner pohon.
Ketika Anda memilikinya dalam bentuk postfix, maka itu sangat mudah sejak saat itu karena Anda sudah memahami bagaimana tumpukan membantu.
sumber
Saya akan menyarankan curang dan menggunakan Algoritma Halaman Shunting . Ini adalah cara mudah untuk menulis parser jenis kalkulator sederhana dan lebih diutamakan.
Jika Anda ingin melakukan tokenisasi dengan benar dan memiliki variabel, dll. Yang terlibat maka saya akan melanjutkan dan menulis parser keturunan rekursif seperti yang disarankan oleh orang lain di sini, namun jika Anda hanya memerlukan parser bergaya kalkulator maka algoritme ini harus cukup :-)
sumber
Saya menemukan ini di PIClist tentang algoritma Shunting Yard :
-Adam
sumber
Sumber daya lain untuk penguraian prioritas adalah entri parser prioritas Operator di Wikipedia. Meliputi algoritme shunting yard Dijkstra, dan algoritme alternatif pohon, tetapi yang lebih khusus mencakup algoritme pengganti makro yang sangat sederhana yang dapat diimplementasikan dengan mudah di depan pengurai mengabaikan prioritas apa pun:
Panggil sebagai:
Yang mengagumkan dalam kesederhanaannya, dan sangat bisa dimengerti.
sumber
Saya telah memposting sumber untuk Penilai Matematika Java ultra kompak (1 kelas, <10 KiB) di situs web saya. Ini adalah pengurai keturunan rekursif dari jenis yang menyebabkan ledakan tengkorak untuk poster jawaban yang diterima.
Ini mendukung prioritas penuh, tanda kurung, variabel bernama dan fungsi argumen tunggal.
sumber
saya merilis pengurai ekspresi berdasarkan algoritma Dijkstra's Shunting Yard , di bawah persyaratan Lisensi Apache 2.0 :
http://projects.congrace.de/exp4j/index.html
sumber
Saya telah mengimplementasikan parser keturunan rekursif di Java dalam proyek MathEclipse Parser . Ini juga dapat digunakan sebagai modul Google Web Toolkit
sumber
Saat ini saya mengerjakan serangkaian artikel yang membangun pengurai ekspresi reguler sebagai alat pembelajaran untuk pola desain dan program yang dapat dibaca. Anda dapat melihat kode yang dapat dibaca . Artikel ini menyajikan penggunaan yang jelas dari algoritma yard shunting.
sumber
Saya menulis pengurai ekspresi di F # dan menulis blog tentang itu di sini . Ini menggunakan algoritma halaman shunting, tetapi alih-alih mengubah dari infix ke RPN, saya menambahkan tumpukan kedua untuk mengakumulasi hasil perhitungan. Ini menangani prioritas operator dengan benar, tetapi tidak mendukung operator unary. Saya menulis ini untuk mempelajari F #, bukan untuk mempelajari penguraian ekspresi.
sumber
Solusi Python menggunakan pyparsing dapat ditemukan di sini . Parsing notasi infix dengan berbagai operator dengan prioritas cukup umum, dan pyparsing juga mencakup pembangun ekspresi
infixNotation
(sebelumnyaoperatorPrecedence
). Dengan itu Anda dapat dengan mudah mendefinisikan ekspresi boolean menggunakan "AND", "OR", "NOT", misalnya. Atau Anda dapat memperluas aritmatika empat fungsi Anda untuk menggunakan operator lain, seperti! untuk faktorial, atau '%' untuk modulus, atau tambahkan operator P dan C untuk menghitung permutasi dan kombinasi. Anda bisa menulis parser infix untuk notasi matriks, yang mencakup penanganan operator '-1' atau 'T' (untuk inversi dan transpos). Contoh operatorPrecedence dari parser 4 fungsi (dengan '!'.sumber
Saya tahu ini adalah jawaban yang terlambat, tetapi saya baru saja menulis parser kecil yang memungkinkan semua operator (awalan, postfix dan infix-left, infix-right dan nonassociative) memiliki prioritas yang sewenang-wenang.
Saya akan mengembangkan ini untuk bahasa dengan dukungan DSL sewenang-wenang, tetapi saya hanya ingin menunjukkan bahwa seseorang tidak memerlukan parser khusus untuk prioritas operator, seseorang dapat menggunakan parser umum yang tidak memerlukan tabel sama sekali, dan hanya mencari prioritas setiap operator seperti yang terlihat. Orang-orang telah menyebutkan pengurai Pratt khusus atau pengurai halaman shunting yang dapat menerima masukan ilegal - yang ini tidak perlu disesuaikan dan (kecuali ada bug) tidak akan menerima masukan yang buruk. Dalam arti tertentu, ini tidak lengkap, itu ditulis untuk menguji algoritme dan masukannya dalam bentuk yang memerlukan beberapa pemrosesan awal, tetapi ada komentar yang membuatnya jelas.
Perhatikan beberapa jenis operator yang umum hilang misalnya jenis operator yang digunakan untuk mengindeks yaitu tabel [indeks] atau memanggil fungsi fungsi (parameter-ekspresi, ...) Saya akan menambahkannya, tetapi anggap keduanya sebagai postfix operator di mana apa yang muncul di antara pembatas '[' dan ']' atau '(' dan ')' diuraikan dengan contoh pengurai ekspresi yang berbeda. Maaf telah mengabaikannya, tetapi bagian postfix ada - menambahkan sisanya mungkin akan hampir menggandakan ukuran kode.
Karena parser hanya 100 baris kode raket, mungkin saya harus menempelkannya di sini, saya harap ini tidak lebih lama dari yang diizinkan oleh stackoverflow.
Beberapa detail tentang keputusan sewenang-wenang:
Jika operator postfix prioritas rendah bersaing untuk blok infiks yang sama sebagai operator awalan prioritas rendah, operator awalan menang. Ini tidak muncul di sebagian besar bahasa karena kebanyakan tidak memiliki operator postfix dengan prioritas rendah. - misalnya: ((data a) (left 1 +) (pre 2 not) (data b) (post 3!) (left 1 +) (data c)) adalah a + bukan b! + c dimana tidak adalah a operator awalan dan! adalah operator postfix dan keduanya memiliki prioritas lebih rendah dari + sehingga mereka ingin mengelompokkan dengan cara yang tidak kompatibel baik sebagai (a + bukan b!) + c atau sebagai + (bukan b! + c) dalam kasus ini operator awalan selalu menang, sehingga kedua adalah cara mengurai
Operator infix non-asosiatif benar-benar ada sehingga Anda tidak perlu berpura-pura bahwa operator yang mengembalikan tipe berbeda dari yang mereka anggap masuk akal, tetapi tanpa memiliki tipe ekspresi yang berbeda untuk masing-masing itu adalah kludge. Dengan demikian, dalam algoritme ini, operator non-asosiatif menolak untuk mengasosiasikan tidak hanya dengan diri mereka sendiri tetapi juga dengan operator apa pun dengan prioritas yang sama. Itu adalah kasus umum karena <<= ==> = etc tidak terkait satu sama lain dalam banyak bahasa.
Pertanyaan tentang bagaimana jenis operator yang berbeda (kiri, awalan, dll) memutuskan hubungan pada prioritas adalah pertanyaan yang seharusnya tidak muncul, karena tidak masuk akal untuk memberi operator dari jenis yang berbeda prioritas yang sama. Algoritme ini melakukan sesuatu dalam kasus-kasus itu, tetapi saya bahkan tidak repot-repot mencari tahu dengan tepat apa karena tata bahasa seperti itu adalah ide yang buruk sejak awal.
sumber
Berikut adalah solusi rekursif kasus sederhana yang ditulis dalam Java. Perhatikan bahwa ini tidak menangani angka negatif tetapi Anda dapat menambahkannya jika Anda ingin:
}
sumber
Algoritma dapat dengan mudah dikodekan dalam C sebagai pengurai keturunan rekursif.
libs berikutnya mungkin berguna: yupana - operasi aritmatika yang ketat; tinyexpr - operasi aritmatika + fungsi matematika C + yang disediakan oleh pengguna; mpc - kombinator parser
Penjelasan
Mari kita tangkap urutan simbol yang mewakili ekspresi aljabar. Yang pertama adalah angka, yaitu digit desimal yang diulang satu kali atau lebih. Kami akan merujuk notasi seperti itu sebagai aturan produksi.
Operator penjumlahan dengan operannya adalah aturan lain. Ini adalah salah satu
number
atau simbol apa pun yang mewakilisum "*" sum
urutan.Coba gantikan
number
dengansum "+" sum
yang nantinyanumber "+" number
bisa diperluas menjadi[0..9]+ "+" [0..9]+
yang akhirnya bisa direduksi menjadi1+8
ekspresi penjumlahan yang benar.Substitusi lain juga akan menghasilkan ekspresi yang benar:
sum "+" sum
->number "+" sum
->number "+" sum "+" sum
->number "+" sum "+" number
->number "+" number "+" number
->12+3+5
Sedikit demi sedikit kita bisa menyerupai seperangkat aturan produksi alias tata bahasa yang mengekspresikan semua kemungkinan ekspresi aljabar.
Untuk mengontrol prioritas operator mengubah posisi aturan produksinya terhadap yang lain. Perhatikan tata bahasa di atas dan perhatikan bahwa aturan produksi untuk
*
ditempatkan di bawah+
ini akan memaksaproduct
evaluasi sebelumnyasum
. Implementasi hanya menggabungkan pengenalan pola dengan evaluasi dan dengan demikian mencerminkan aturan produksi.Di sini kita mengevaluasi
term
terlebih dahulu dan mengembalikannya jika tidak ada*
karakter setelah itu pilihan kiri dalam aturan produksi kita sebaliknya - mengevaluasi simbol setelah dan mengembalikanterm.value * product.value
ini adalah pilihan yang benar dalam aturan produksi kita yaituterm "*" product
sumber