<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Dajak Logs</title>
	<atom:link href="http://dajak.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://dajak.wordpress.com</link>
	<description>Monthly logs of a computer language aficionado</description>
	<lastBuildDate>Mon, 18 Jan 2010 03:46:37 +0000</lastBuildDate>
	<language>id</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='dajak.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Dajak Logs</title>
		<link>http://dajak.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://dajak.wordpress.com/osd.xml" title="Dajak Logs" />
	<atom:link rel='hub' href='http://dajak.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Merakit sendiri lingkungan pemrograman ActionScript</title>
		<link>http://dajak.wordpress.com/2010/01/18/merakit-sendiri-lingkungan-pemrograman-actionscript/</link>
		<comments>http://dajak.wordpress.com/2010/01/18/merakit-sendiri-lingkungan-pemrograman-actionscript/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 03:46:37 +0000</pubDate>
		<dc:creator>Adhi Hargo</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Emacs]]></category>

		<guid isPermaLink="false">http://dajak.wordpress.com/?p=56</guid>
		<description><![CDATA[Wah, sudah hampir satu tahun persis blog ini saya tinggalkan. Alasan pertamanya sederhana: life interferes Alasan kedua atas kemalasan saya di blog ini, adalah saya sedang jenuh mempelajari desain bahasa dan teknik kompilasi (kapan-kapan balik, it&#8217;s my deepest passion), pindah mempelajari bagaimana memproduksi film animasi sendiri. Resolusi 2010 saya, harus sudah memproduksi setidaknya satu film [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=56&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Wah, sudah hampir satu tahun persis blog ini saya tinggalkan. Alasan pertamanya sederhana: <em>life interferes</em> <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Alasan kedua atas kemalasan saya di blog ini, adalah saya sedang jenuh mempelajari desain bahasa dan teknik kompilasi (kapan-kapan balik, <em>it&#8217;s my deepest passion</em>), pindah mempelajari bagaimana memproduksi film animasi sendiri. Resolusi 2010 saya, harus sudah memproduksi setidaknya satu film pendek animasi. Software yang saya gunakan adalah <a href="http://blender.org/">Blender 3D</a>, dan waktu dan kapasitas otak yang tersisa setelah mempelajari animasi dan sketsa (untuk storyboarding dan desain karakter), saya gunakan untuk memprogram perangkat-perangkat tambahan untuk Blender agar memudahkan proses menjadi <a href="http://www.wired.com/entertainment/hollywood/news/2008/04/sita">One-Man Pixar</a> <img src='http://s2.wp.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Menggambar dan animasi ternyata susah, dan pikiran saya kadang kelayapan kembali ke pemrograman. Satu bidang yang menjembatani keduanya adalah pemrograman grafis, dan selama 1 tahun terakhir di waktu luang saya mengakrabkan diri dengan bahasa-bahasa pemrograman grafis <a href="http://www.tailrecursive.org/postscript/postscript.html">PostScript</a>, <a href="http://processing.org/">Processing</a>, dan yang terakhir: <a href="http://www.actionscript.org/">ActionScript</a>. Di antara ketiganya saya paling menyukai ActionScript, karena lebih manusiawi dari PostScript dan lebih mudah diajak eksperimen ketimbang Processing (sayangnya berbasis Java dan sulit menguji program lewat command-line).</p>
<p>Meski tersedia IDE semacam <a href="http://www.adobe.com/products/flex/features/flex_builder/">Flex Builder</a> atau <a href="http://www.flashdevelop.org/">Flash Develop</a>, dalam menciptakan lingkungan pemrograman ActionScript yang nyaman, saya kembali bergantung pada <a href="http://www.gnu.org/software/emacs/">GNU Emacs</a> tercinta, dan menambahkan paket/file berikut:</p>
<ul>
<li><strong>Adobe Flex</strong> [<a href="http://www.adobe.com/products/flex/">URL</a>] dan/atau <strong>SWFTools</strong> [<a href="http://swftools.org/">URL</a>].  Diperlukan untuk mengkompilasi file <code>.as</code> kode sumber program menjadi file Flash <code>.swf</code>. Kompiler SWFTools <code>as3compile</code> adalah yang waktu kompilasinya paling cepat dan berukuran paling kecil di antara kedua pilihan ini, namun kompiler Adobe Flex <code>mxmlc</code> lebih ketat memberlakukan sintaks ActionScript, ditambah bonus komponen-komponen Flex yang memudahkan kita sewaktu-waktu menciptakan Rich Internet Application.</li>
<li><strong>Adobe Flash Player &#8211; Debugger Version</strong> [<a href="http://www.adobe.com/support/flashplayer/downloads.html">URL</a>].  Diperlukan untuk menguji file Flash yang dihasilkan. Versi player Flash ini memudahkan debugging program-program ActionScript, termasuk mencetak perintah tracing ke <code>stdout</code>.</li>
<li><strong>Emacs ActionScript mode</strong> [<a href="http://www.emacswiki.org/emacs/ActionScriptMode">URL</a>]. Di antara berbagai versi yang ditawarkan, saya paling sreg dengan <a href="http://www.emacswiki.org/emacs/actionscript-mode-connors.el">buatan John Connors</a> (HTML, jangan langsung &quot;Save As&#8230;&quot;), turunan dialek Java dari <code>cc-mode</code>.</li>
<li><strong>Dokumentasi ActionScript + Adobe Flex</strong> [<a href="http://www.adobe.com/support/documentation/en/flex/">URL</a>].  Tersedia satu file arsip berisi seluruh dokumentasi offline ActionScript dan Adobe Flex dalam format HTML dengan ukuran total cukup besar, 100MB++, yang kemudian saya ubah menjadi file <code>.chm</code> HTML Help berukuran 17MB.</li>
</ul>
<p>Terakhir, saya tambahkan aturan khusus ActionScript berikut ke dalam <code>Makefile</code> generik (daftar <code>Makefile</code> yang digunakan GNU Make bila tidak ditemukan makefile per-proyek, ditentukan dalam env-variable <code>MAKEFILES</code>):</p>
<pre class="src"><span style="color:#b22222;"># </span><span style="color:#b22222;">Actionscript
</span><span style="color:#b8860b;">SWFWIDTH</span> = 640
<span style="color:#b8860b;">SWFHEIGHT</span> = 480
<span style="color:#b8860b;">FLASHPRJ</span> = flashplayer_10_sa_debug.exe
<span style="color:#b8860b;">AS3COMPILE</span> = as3compile --width $(<span style="color:#b8860b;">SWFWIDTH</span>) --height $(<span style="color:#b8860b;">SWFHEIGHT</span>)
<span style="color:#b8860b;">MXMLC</span> = mxmlc -default-background-color=0x7f7f7f \
        -default-size=$(<span style="color:#b8860b;">SWFWIDTH</span>),$(<span style="color:#b8860b;">SWFHEIGHT</span>)
<span style="color:#0000ff;">%_st.swf</span>: %.as
        $(<span style="color:#b8860b;">AS3COMPILE</span>) $<span style="color:#5f9ea0;">^</span> -o <span style="color:#0000ff;">$</span><span style="color:#5f9ea0;">@</span> --width 800 --height 600

<span style="color:#0000ff;">%.swf</span>: %.as
        $(<span style="color:#b8860b;">MXMLC</span>) $<span style="color:#5f9ea0;">^</span> -o <span style="color:#0000ff;">$</span><span style="color:#5f9ea0;">@</span>

<span style="color:#0000ff;">%_test</span>: %.swf
        $(<span style="color:#b8860b;">FLASHPRJ</span>) $<span style="color:#5f9ea0;">^</span>

<span style="color:#0000ff;">%.html</span>:: %.swf
        <span style="color:#228b22;">@</span>echo <span style="color:#bc8f8f;">'&lt;object width="$(</span><span style="color:#b8860b;">SWFWIDTH</span><span style="color:#bc8f8f;">)" height="$(</span><span style="color:#b8860b;">SWFHEIGHT</span><span style="color:#bc8f8f;">)"&gt;'</span> \
                <span style="color:#bc8f8f;">'&lt;param name="movie" value="$</span><span style="color:#5f9ea0;">^</span><span style="color:#bc8f8f;">"&gt;'</span> \
                <span style="color:#bc8f8f;">'&lt;embed src="$</span><span style="color:#5f9ea0;">^</span><span style="color:#bc8f8f;">" width="$(</span><span style="color:#b8860b;">SWFWIDTH</span><span style="color:#bc8f8f;">)"'</span>\
                <span style="color:#bc8f8f;">' height="$(</span><span style="color:#b8860b;">SWFHEIGHT</span><span style="color:#bc8f8f;">)"&gt;'</span> \
                <span style="color:#bc8f8f;">'&lt;/embed&gt;&lt;/object&gt;'</span> &gt; <span style="color:#0000ff;">$</span><span style="color:#5f9ea0;">@</span>
</pre>
<p>&#8230; sehingga untuk menguji file <code>XYZ.as</code> saya hanya perlu menjalankan perintah <code>make XYZ_test</code> (yang dalam Emacs saya petakan ke satu tombol dengan fungsi Emacs-Lisp).</p>
<p>Kesan saya tentang ActionScript sejauh ini positif. Sekadar membuat program ActionScript untuk <em>credit-roll</em> film sangatlah mudah (dan jauh lebih cepat di-render ketimbang jika membuatnya sebagai scene 3D dalam Blender), mungkin saya akan mengusulkannya untuk <a href="http://blenderindonesia.org/seruling/">Seruling Project</a>-nya Blender Indonesia di mana saya turut terlibat (jelas open source, jelas punya keunggulan, tinggal presentasinya seperti apa&#8230;).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/dajak.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/dajak.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/dajak.wordpress.com/56/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=56&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://dajak.wordpress.com/2010/01/18/merakit-sendiri-lingkungan-pemrograman-actionscript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cbe5c58a8154ae278d59048a7acfdf2b?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">adhi</media:title>
		</media:content>
	</item>
		<item>
		<title>Software Sebagai Produk vs Software Sebagai Jasa</title>
		<link>http://dajak.wordpress.com/2009/03/08/software-sebagai-produk-vs-software-sebagai-jasa/</link>
		<comments>http://dajak.wordpress.com/2009/03/08/software-sebagai-produk-vs-software-sebagai-jasa/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 11:56:03 +0000</pubDate>
		<dc:creator>Adhi Hargo</dc:creator>
				<category><![CDATA[Menulis]]></category>

		<guid isPermaLink="false">http://dajak.wordpress.com/?p=54</guid>
		<description><![CDATA[Sejak pertama mengetahui keberadaan bahasa Nusa (dulu Batak), saya selalu rutin mencari tahu kabar perkembangannya. Maklum, model distribusi kompiler untuknya saat ini tidak lazim saya temui, yaitu melalui milis privat di Yahoo! Groups namun dengan pengumuman publik. Saya coba registrasi (ini sebelum memulai pengembangan bahasa saya sendiri, saat ini Jeruk), namun tidak ditanggapi. Tak apalah, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=54&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Sejak pertama mengetahui keberadaan bahasa Nusa (dulu Batak), saya selalu rutin mencari tahu kabar perkembangannya. Maklum, model distribusi kompiler untuknya saat ini tidak lazim saya temui, yaitu melalui milis privat di Yahoo! Groups namun dengan pengumuman publik. Saya coba registrasi (ini sebelum memulai pengembangan bahasa saya sendiri, saat ini Jeruk), namun tidak ditanggapi. Tak apalah, malah jadi disibukkan urusan sendiri saja.</p>
<p>Akhir Februari lalu, saat penasaran lagi dengan Nusa, saya temui artikel menarik di <a href="http://bernaridho.net/">situs</a> Pak Bernaridho, pencipta bahasa ini. Mungkin beliau terkadang melakukan <em>narcissism-search</em> &mdash;seperti saya juga <img src='http://s2.wp.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  &mdash; karena di sana beliau merespon <a href="http://syamsuddin-ideris.blogspot.com/2009/02/pc-media-pembodohan-pembaca.html">kritik pedas</a> seorang blogger dari Kalimantan Selatan yang, meski judulnya salah alamat, diarahkan pada pandangan beliau tentang software bebas. Sepintas lalu artikel Pak Bernaridho memang terkesan menghina software bebas, namun berkat tanggapan ini segala isu yang keruh bagi saya menjadi jelas, bahkan akhirnya mempengaruhi perspektif saya sendiri. Maka sebelum saya lancarkan tanggapan saya secara penuh, saya ucapkan terima kasih baik pada Pak Syamsuddin Ideris yang berani memulai proses dialektik ini maupun Pak Bernaridho Hutabarat yang bersedia merespon dengan kepala dingin.</p>
<p>Para pengembang software profesional tentu telah familiar dengan inti catatan; saya hanya mempertegas saja konsep yang jarang ditekankan dalam artikel lain. <em>Now, on with the show!</em></p>
<p><span id="more-54"></span></p>
<h2>Software sebagai Produk</h2>
<p class="first">Saya yakin Anda akrab dengan software yang dipasarkan sebagai produk. Dikemas dengan profesional, didistribusikan lengkap dengan buku manual, garansi dan dukungan konsumen, dan diberi label harga seperti rata-rata produk konsumen. Harga produk software telah memperhitungkan segala biaya konstruksinya, termasuk biaya <em>intangible</em> berupa kompensasi terhadap beban intelektual yang diemban para pemrogram software yang dimaksud saat menciptakannya. Mereka tidak menyebutnya demikian, tentu saja, karena biaya tersebut telah difaktorkan ke dalam remunerasi untuk masing-masing pemrogram.</p>
<p>Di sinilah terletak justifikasi untuk memperlakukan software selayaknya sebuah produk konsumen. Semua biaya tersebut <em>nyata</em> meski inti dari produk akhirnya adalah kombinasi berbagai mekanisme dan implementasi algoritma kompleks yang <em>abstrak</em>, bukan rangkaian bit pseudorandom. <strong>Seribu simpanse memukul-mukul tombol seribu mesin ketik selama seribu tahun tidak akan menghasilkan karya Shakespeare, apalagi Windows XP!</strong> Kita <em>tahu</em> bahwa para pemrogram tersebut <em>layak</em> atas gaji pertahun US$ 60.000 ke atas. Kita <em>tahu</em> bahwa merakit sebuah software komersial bukan pekerjaan mudah.</p>
<p>Tapi pada pengetahuan tersebut pula, terletak kelemahan yang saat ini membatasi model bisnis ini, dan industri software dalam negeri secara keseluruhan: rata-rata masyarakat Indonesia <em>tidak tahu</em> bahwa menciptakan software itu sulit, apa lagi yang berkualitas tinggi. Yang mereka tahu adalah mereka ingin memanfaatkan komputer dengan mudah, dan bila software komersial-lah solusi terbaik, itulah yang mereka gunakan. Dan bila menggunakannya secara ilegal adalah solusi termudah, itulah yang akan mereka lakukan! Produsen software yang tidak turut mempertimbangkan bahwa karya mereka, berapapun harganya, cepat atau lambat akan muncul pula di Glodok dengan harga per DVD Rp 30.000 harus bersiap-siap menelan kekecewaan.</p>
<p>Bill Gates kurang-lebih mempopulerkan model bisnis ini sejak tahun 1976, saat mempublikasikan suratnya yang turut menandai lahirnya industri software, <a href="http://www.blinkenlights.com/classiccmp/gateswhine.html">An Open Letter to Hobbyists</a>. Di sana ia berujar sederhana,</p>
<blockquote>
<p class="quoted">Who can afford to do professional work for nothing?</p>
</blockquote>
<p>Ya, masuk akal jika kita turut bertanya: siapa yang mau membuat software berkualitas tinggi tanpa imbalan? Dan kita akan lihat, bahwa model bisnis alternatifnya-pun tetap tunduk pada hukum alam yang sederhana ini.</p>
<h2>Software sebagai Jasa</h2>
<p class="first">Selain sebagai produk, software juga dapat dipandang sebagai jasa, atau pelengkap jasa. Kemunculan model alternatif ini ditandai, tentu saja, dengan pemunculan software bebas. Bentuknya bervariasi, dari yang ideologis (<a href="http://fsf.org/">Free Software Foundation</a>) sampai pragmatis (<a href="http://opensource.org/">Open Source Initiative</a>). Untuk memahami logika dari model bisnis yang menggunakan software sebagai pelengkap jasa, kita mulai saja dengan menganggap pekerjaan para sukarelawan kontributor software bebas sebagai <em>pendanaan tidak langsung</em>. Mereka telah memiliki sumber penghidupan yang memadai, sehingga tidak memusingkan profit saat menyumbangkan waktu, tenaga dan pikiran mereka pada sebuah proyek software bebas. Diluar pendanaan tidak langsung tersebut &mdash;dan donasi&mdash; sebenarnya banyak cara lain yang digunakan pengelola software bebas untuk mendukung kesinambungan pengembangan produk mereka, misalnya:</p>
<ul>
<li><a href="http://wxwidgets.org/">wxWidgets</a> didukung pula oleh penjualan perangkat bantu konstruksi program semacam <a href="http://roebling.de/">wxDesigner</a> atau <a href="http://anthemion.co.uk/dialogblocks">DialogBlocks</a> yang diciptakan oleh para kontributor utama wxWidgets, secara berturutan, Robert Roebling dan Julian Smart.</li>
<li>Bahasa <a href="http://processing.org/">Processing</a> didukung pula oleh penjualan buku-buku tentang pemanfaatan bahasa pemrograman visual tersebut.</li>
<li><a href="http://gcc.gnu.org/">GCC</a> didukung pula oleh, di antaranya, perusahaan konsultansi semacam Cygnus Support (sekarang bagian dari Red Hat) yang menjual kepakaran dan keakraban mereka dengan GCC (mampu membangun backend untuk mikroprosesor baru, atau porting ke platform baru, misalnya), atau para akademisi yang menggunakan GCC dalam riset dengan dana pihak ketiga.</li>
<li>Software blog semacam <a href="http://wordpress.org/">WordPress</a> atau <a href="http://movabletype.org/">Movable Type</a> didukung pula oleh jasa hosting blog, atau komersialisasi fitur &quot;Pro&quot; dari layanan mereka.</li>
<li><a href="http://blender3d.org/">Blender</a> didukung pula oleh penjualan buku/video berbagai tutorial dan referensi penggunaan Blender, serta penjualan produk-produk &mdash;saat ini setidaknya dua buah film (<a href="http://www.elephantsdream.org/">Elephant&#8217;s Dream</a> dan <a href="http://www.bigbuckbunny.org/">Big Buck Bunny</a>) serta satu buah game (<a href="http://www.yofrankie.org/">Yo, Frankie!</a>)&mdash; yang diciptakan dengan Blender.</li>
<li><a href="http://imagemagick.org/">ImageMagick</a> didukung pula oleh penjualan lisensi penggunaan komersial, serta setidaknya dua buku tentang penggunaan perangkat tersebut.</li>
<li><a href="http://httpd.apache.org/">Apache</a> didukung pula oleh pendanaan dari IBM, yang menilai bahwa server-HTTP dengan biaya terjangkau dapat mendukung penjualan produk server mereka.</li>
<li>GNU/Linux didukung pula oleh perusahaan semacam <a href="http://redhat.com/">Red Hat</a> atau <a href="http://mandriva.com/">Mandriva</a> yang menjual distribusi ramah-pengguna dari sistem operasi tersebut, dengan buku referensi dan panduan penggunaan, serta menyewakan dukungan konsumen pada pengguna korporat.</li>
</ul>
<p>Tidak saya ragukan bahwa masih banyak sumber pendanaan lain untuk menjaga kelangsungan hidup sebuah proyek software bebas (termasuk yang disebut di atas), terutama untuk software dengan manfaat luas seperti GNU/Linux. Yang ingin saya garis bawahi dari contoh (yang sangat tidak lengkap) di atas adalah sebuah pola umum, berupa <strong>peletakan masing-masing software dalam sebuah kerangka bisnis yang lebih luas</strong>: entah itu digabungkan dengan penyediaan jasa (konsultansi, dukungan konsumen) atau penjualan produk (hardware server, buku, perangkat bantu pemrograman), atau keduanya. Software bebas yang berhasil jarang berdiri sendiri: hampir selalu ada dukungan dari pihak-pihak yang dapat memanfaatkannya secara ekonomis.</p>
<p>Memang ada software bebas yang tidak memenuhi &quot;pola umum&quot; tersebut, misalnya (CMIIW) <a href="http://www.mediawiki.org/">MediaWiki</a> yang &mdash;dibawah naungan <a href="http://www.wikimediafoundation.org/">Wikimedia Foundation</a>&mdash; secara eksklusif bergantung pada donasi. Satu hal yang saya kritik dari pandangan Pak Bernaridho, meminta donasi tidak harus identik dengan mengemis, dan memberi donasi tentu tidak sama dengan berbelas kasihan. Perspektif lain yang lebih positif adalah <strong>Set Your Own Price</strong> (<em>&quot;If you found this software as useful, please consider donating!&quot;</em>) atau <strong>Do For Greater Good</strong> (<a href="http://wikipedia.org/">Wikipedia</a>: <em>&quot;Lots of others found Wikipedia useful, please consider donating!&quot;</em>).</p>
<h2>Perkembangan di Indonesia</h2>
<p class="first">Mengenai perubahan taktik promosi IGOS oleh Depkominfo yang diutarakan Pak Bernaridho, saya hanya bisa tersenyum karena sudah sejak lama dapat menebak, bahwa mental senang-gratisan orang Indonesia tidak dapat dimanipulasi untuk menguntungkan software bebas, karena tidak dibarengi dengan pemahaman etis yang sinkron. Sampai sekarang, bagi saya IGOS lebih identik dengan seremoni-seremoni khas pemerintah, ketimbang gebrakan nyata.</p>
<p>Untungnya, tanpa gegap-gempita IGOS pun dunia usaha mulai merespon positif keberadaan software bebas. BusinessWeek Indonesia edisi bulan ini (Maret 2009) turut meliput beberapa korporasi dalam negeri yang melakukan migrasi ke sistem open source berbasis platform GNU/Linux. Rata-rata proses migrasi baru berjalan beberapa tahun, dan yang relatif paling matang sepertinya adalah PT TELKOM, yang telah memulainya sejak tahun 2000.</p>
<p>Saya tidak dapat mengambil kesimpulan definitif dari fakta-fakta semacam itu, namun tanda-tandanya mulai jelas, bahwa dunia usaha secara umum mulai dapat menerima penggunaan software bebas. Setidaknya tiga tahun terakhir saya lihat mulai banyak perusahaan konsultansi dan perangkat lunak web bermunculan, yang percaya diri menggunakan platform LAMP. Itu pun gejala yang cukup baik. Intinya &mdash;dan ini kesimpulan yang sudah basi sekali, meski banyak yang belum mengerti&mdash; software bebas tidak dapat dengan serta-merta diidentikkan dengan &quot;amatiran&quot; atau &quot;pengemis&quot;. Banyak software bebas (buatan orang luar Indonesia) yang <em>robust</em> dan berkualitas tinggi, serta dapat bernilai ekonomis bagi penciptanya tanpa melulu bergantung pada donasi. Tinggal komunitas pemrogram Indonesia &mdash;saya, Anda, dan semua rekan kita&mdash; yang harus membuktikannya dalam konteks software buatan dalam negeri!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/dajak.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/dajak.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/dajak.wordpress.com/54/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=54&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://dajak.wordpress.com/2009/03/08/software-sebagai-produk-vs-software-sebagai-jasa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cbe5c58a8154ae278d59048a7acfdf2b?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">adhi</media:title>
		</media:content>
	</item>
		<item>
		<title>The Quick and The Dead-Slow: Dua cara merakit scanner menggunakan regex</title>
		<link>http://dajak.wordpress.com/2009/01/21/dua-cara-merakit-scanner-menggunakan-regex/</link>
		<comments>http://dajak.wordpress.com/2009/01/21/dua-cara-merakit-scanner-menggunakan-regex/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 08:34:17 +0000</pubDate>
		<dc:creator>Adhi Hargo</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Scheme]]></category>

		<guid isPermaLink="false">http://dajak.wordpress.com/?p=50</guid>
		<description><![CDATA[Biasanya kalau baru membaca kode sumber sebuah program pemroses bahasa, saya memulai dari struktur data internal yang dimodifikasi pertama kali, kemudian mencari komponen penganalisa leksikal. Waktu saya membaca kode sumber interpreter bahasa pemrograman BAIK (asli Indonesia!), ada satu hal yang menarik perhatian saya: program ini menggunakan pustaka ekspresi regular generik sebagai komponen lexer-nya. Seperti kita [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=50&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Biasanya kalau baru membaca kode sumber sebuah program pemroses bahasa, saya memulai dari struktur data internal yang dimodifikasi pertama kali, kemudian mencari komponen penganalisa leksikal. Waktu saya membaca kode sumber interpreter <a href="http://sourceforge.net/projects/baik">bahasa pemrograman BAIK</a> (asli Indonesia!), ada satu hal yang menarik perhatian saya: program ini menggunakan pustaka ekspresi regular generik sebagai komponen lexer-nya. Seperti kita ketahui, pustaka ekspresi regular itu <a href="http://en.wikipedia.org/wiki/Swiss_Army_knife">pisau Swiss Army</a>-nya pemrosesan teks. Dari sekadar mencari teks, membaca tabel CSV, validasi input, sampai <a href="http://weblogs.asp.net/cazzu/archive/2005/01/10/RegexParsing.aspx">analisa sintaksis</a> untuk bahasa pemrograman dapat dilakukan olehnya. Segera terlintas di benak saya, bahwa ini bukan solusi optimal, sampai saya pikirkan lagi bahwa mungkin keputusan penggunaan pustaka generik tersebut oleh Pak Haris Hasanudin memiliki dasar yang rasional. Kenapa tidak?</p>
<p>Jadinya kali ini saya hanya akan menggunakan cerita tentang implementasi scanner BAIK sebagai konteks untuk sebuah dongeng, tentang ekspresi regular dan dua cara umum dalam memanfaatkannya untuk memproses bahasa pemrograman. Seperti sebelumnya, akan saya sertakan program-program pendek yang mengilustrasikan kedua pendekatan tersebut, yaitu sebuah pustaka ekspresi regular&#8230;</p>
<pre class="src">
&gt; <span style="color:#cd0000;">((</span>build-regexp-matcher <span style="color:#008b00;">"ba+c?b"</span><span style="color:#cd0000;">)</span> <span style="color:#008b00;">"baaaaaaaaab"</span><span style="color:#cd0000;">)</span>
<span style="color:#008b00;">#t</span>
&gt; <span style="color:#cd0000;">((</span>build-regexp-matcher <span style="color:#008b00;">"ba+c?b"</span><span style="color:#cd0000;">)</span> <span style="color:#008b00;">"bacb"</span><span style="color:#cd0000;">)</span>
<span style="color:#008b00;">#t</span>
</pre>
<p>&#8230; dan sebuah pembangkit scanner untuk bahasa C.</p>
<pre class="src">
&gt; (generate-regexp-matcher-c-code <span style="color:#bc8f8f;">"ba+c?b"</span>)
<span style="color:#228b22;">int</span> <span style="color:#0000ff;">match</span>( <span style="color:#228b22;">char</span>* <span style="color:#b8860b;">cstr</span> ) {
   <span style="color:#228b22;">char</span>* <span style="color:#b8860b;">c</span> = cstr;
   <span style="color:#a020f0;">if</span>( c &amp;&amp; *c == <span style="color:#bc8f8f;">'b'</span> ) {
      ++c;
      <span style="color:#a020f0;">if</span>( c &amp;&amp; *c == <span style="color:#bc8f8f;">'a'</span> ) {
         ++c;
         <span style="color:#a020f0;">while</span>( c &amp;&amp; *c == <span style="color:#bc8f8f;">'a'</span> ) ++c;
         <span style="color:#a020f0;">if</span>( c &amp;&amp; *c == <span style="color:#bc8f8f;">'c'</span> ) ++c;
         <span style="color:#a020f0;">if</span>( c &amp;&amp; *c == <span style="color:#bc8f8f;">'b'</span> ) {
            ++c;
            <span style="color:#a020f0;">return</span> 1;
         }
      }
   }
   <span style="color:#a020f0;">return</span> 0;
}
&gt;
</pre>
<p>Meski program ini sederhana dan ringkas (agar saya tidak dikira sedang bersaing panjang-panjangan blog dengan <a href="http://steve-yegge.blogspot.com/">Steve Yegge</a>), namun ia memadai untuk tujuan saya dan masih membuka kesempatan bagi yang berminat untuk mengembangkannya.</p>
<p><span id="more-50"></span></p>
<h2>Ekspresi Regular</h2>
<p class="first">Di antara keempat tipe grammar dalam Hierarki Chomsky, <a href="http://en.wikipedia.org/wiki/Regular_grammar">Grammar Regular</a> adalah jenis grammar paling efisien untuk mengekspresikan pola linier. Batasan Grammar Regular, menurut &quot;<a href="http://www.cs.vu.nl/~dick/PTAPG.html">Parsing Techniques</a>&quot;-nya Grune dan Jacobs:</p>
<blockquote>
<p class="quoted">[A] right-hand side may only contain one non-terminal and it must come at the end.</p>
</blockquote>
<p>membuat terbayang di benak sebuah mesin yang menjejerkan simbol demi simbol berdasarkan satu set aturan sebuah program, sampai aturan yang digunakan tidak memungkinkan diletakkannya satupun simbol baru. Contohnya grammar berikut:</p>
<p class="verse">
<em>A</em> <code>-&gt;</code> <code>a</code> <em>B</em><br />
<em>B</em> <code>-&gt;</code> <code>b</code> <code>c</code> <em>C</em><br />
<em>C</em> <code>-&gt;</code> <em>A</em><br />
<em>C</em> <code>-&gt;</code>
</p>
<p>Dengan simbol awal <em>A</em>, grammar di atas hanya dapat membangkitkan string &quot;<code>abc</code>&#8230;&quot; secara linier&#8230;</p>
<div id="attachment_49" class="wp-caption aligncenter" style="width: 410px"><img src="http://dajak.files.wordpress.com/2009/01/mesin_regular.jpg?w=400&#038;h=168" alt="Grammar Regular sebagai perangkat pembangkit." title="mesin_regular" width="400" height="168" class="size-full wp-image-49" /><p class="wp-caption-text">Mesin Regular: Grammar Regular sebagai perangkat pembangkit.</p></div>
<p>Kita bisa saja meletakkan aturan tambahan, misalnya</p>
<p class="verse">
<em>C</em> <code>-&gt;</code> <em>B</em> <em>A</em>
</p>
<p>untuk menciptakan percabangan dalam proses produksi kalimat, tapi ini sudah bukan Grammar Regular lagi. Maka ciri khas GR sebagai <em>perangkat pengenal</em><sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup> adalah: Simbol yang ia nantikan hanya bergantung pada simbol yang telah ia temukan dan aturan produksi yang tengah digunakan.</p>
<p>Karakteristik ini mengingatkan kita akan <a href="http://en.wikipedia.org/wiki/Finite_state_machine">automata keadaan-berhingga</a> (<em>finite-state automata</em>), karena pembaca bahasa dengan grammar regular (bahasa regular) hanya perlu menyimpan informasi tentang keadaannya saat itu (<em>state</em>) dan berubah keadaan, diam, atau berhenti membaca pada setiap kata (<em>input</em>). Dengan berbekal struktur data list atau tree, seorang pemrogram dapat dengan mudah membuat program yang mengenali bahasa regular.</p>
<p>Maka sampailah kita pada pembahasan tentang <strong><em>ekspresi regular</em></strong> (<em>regular expression</em>). Meski saya yakin Anda sudah tahu apa itu <a href="http://en.wikipedia.org/wiki/Regular_expression">regex</a> dan bagaimana cara menggunakannya, saya tebak Anda &mdash;seperti juga saya&mdash; belum tahu persis bagaimana fasilitas regex diimplementasikan. Untungnya, dengan membuat prototip fasilitas regex dalam bahasa Scheme setidaknya kita bisa mendapatkan gambaran.</p>
<p>Inti dari prototip ini hanya berupa satu fungsi. Ia hanya mendukung subset pokok dari apa yang kita kenal sebagai &quot;regex&quot; (karena <a href="http://dev.perl.org/perl6/doc/design/apo/A05.html">&quot;regex&quot; sekarang bukan sekadar ekspresi regular lagi</a>). Berikut kode utamanya:</p>
<pre class="src">
<span style="color:#cd0000;">(</span><span style="font-weight:bold;">define</span> <span style="color:#cd0000;">(</span><span style="color:#0000ff;font-weight:bold;">build-regexp-list-pattern</span> list-regexp<span style="color:#cd0000;">)</span>
  <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> loop <span style="color:#cd0000;">([</span>list-regexp list-regexp<span style="color:#cd0000;">]</span> <span style="color:#cd0000;">[</span>fa <span style="color:#cd0000;">(</span>list<span style="color:#cd0000;">)]</span> <span style="color:#cd0000;">[</span>fa-tail <span style="color:#cd0000;">()])</span>
    <span style="color:#cd0000;">(</span><span style="font-weight:bold;">if</span> <span style="color:#cd0000;">(</span>null? list-regexp<span style="color:#cd0000;">)</span>
        <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span>
        <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> <span style="color:#cd0000;">([</span>head <span style="color:#cd0000;">(</span>car list-regexp<span style="color:#cd0000;">)]</span> <span style="color:#cd0000;">[</span>tail <span style="color:#cd0000;">(</span>cdr list-regexp<span style="color:#cd0000;">)])</span>
          <span style="color:#cd0000;">(</span><span style="font-weight:bold;">cond</span>
           <span style="color:#008b8b;">;; Star closure
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\*</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>char? <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'star</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Kleene closure
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\+</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>char? <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'star</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Optional presence
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\?</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>not <span style="color:#cd0000;">(</span>null? fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'opt</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Match-all character
</span>           <span style="color:#cd0000;">[(</span>eq? head <span style="color:#008b00;">#\.</span><span style="color:#cd0000;">)</span>
            <span style="color:#cd0000;">(</span>loop tail <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>list <span style="color:#008b00;">'any</span><span style="color:#cd0000;">))]</span>
           <span style="color:#cd0000;">[</span><span style="font-weight:bold;">else</span>
            <span style="color:#cd0000;">(</span>loop tail <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>list head<span style="color:#cd0000;">))]</span>
           <span style="color:#cd0000;">)))))</span>
</pre>
<p>Fungsi <code>build-regexp-list-pattern</code> di atas memanfaatkan sifat linier Grammar Regular. Ia menerima string regex dalam wujud list (agar tidak perlu proses scan), dan menghasilkan struktur list lain berisi pola kalimat regular. Misalnya,</p>
<pre class="src">
&gt; <span style="color:#cd0000;">(</span>build-regexp-list-pattern <span style="color:#cd0000;">(</span>string-&gt;list <span style="color:#008b00;">"z?ab*c+"</span><span style="color:#cd0000;">))</span>
<span style="color:#cd0000;">((</span>opt <span style="color:#008b00;">#\z</span><span style="color:#cd0000;">)</span> <span style="color:#008b00;">#\a</span> <span style="color:#cd0000;">(</span>star <span style="color:#008b00;">#\b</span><span style="color:#cd0000;">)</span> <span style="color:#008b00;">#\c</span> <span style="color:#cd0000;">(</span>star <span style="color:#008b00;">#\c</span><span style="color:#cd0000;">))</span>
&gt;
</pre>
<p>Sebagai satu bukti bahwa fungsi regex di atas masih dapat dikembangkan, perhatikan bahwa Kleene closure didefinisikan menggunakan star closure: <code>a+</code> sebagai <code>aa*</code>. Fasilitas lain yang dapat kita tambahkan adalah pembatasan frekuensi semacam &quot;<code>x{3,5}</code>&quot;, yang dapat diterjemahkan sebagai &quot;<code>xxxx?x?</code>&quot;. Dengan bekal fungsi sederhana tersebut, kita akan menjelajahi kedua alternatif pemanfaatan regex dalam perakitan komponen scanner dalam pemroses bahasa.</p>
<h2>Teknik #1: Pembangkitan Dinamis</h2>
<p class="first">Teknik ini yang digunakan oleh pustaka regex generik. Karena pustaka semacam ini digunakan untuk berbagai keperluan yang belum tentu dapat diantisipasi penciptanya, string ekspresi regular harus diterjemahkan terlebih dahulu, dan struktur data yang dihasilkannya disimpan dalam memori sepanjang fungsi pengenal ekspresi tersebut masih diperlukan. Misalnya, menggunakan struktur data yang dihasilkan <code>build-regexp-list-pattern</code> kita dapat membuat fungsi validasi sederhana:</p>
<pre class="src">
<span style="color:#cd0000;">(</span><span style="font-weight:bold;">define</span> <span style="color:#cd0000;">(</span><span style="color:#0000ff;font-weight:bold;">build-regexp-matcher</span> regexp<span style="color:#cd0000;">)</span>
  <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> <span style="color:#cd0000;">([</span>pattern <span style="color:#cd0000;">(</span>build-regexp-list-pattern <span style="color:#cd0000;">(</span>string-&gt;list regexp<span style="color:#cd0000;">))])</span>
    <span style="color:#cd0000;">(</span><span style="font-weight:bold;">lambda</span> <span style="color:#cd0000;">(</span>str<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>match-pattern pattern str<span style="color:#cd0000;">))))</span>

<span style="color:#cd0000;">(</span><span style="font-weight:bold;">define</span> <span style="color:#cd0000;">(</span><span style="color:#0000ff;font-weight:bold;">build-regexp-list-pattern</span> list-regexp<span style="color:#cd0000;">)</span>
  <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> loop <span style="color:#cd0000;">([</span>list-regexp list-regexp<span style="color:#cd0000;">]</span> <span style="color:#cd0000;">[</span>fa <span style="color:#cd0000;">(</span>list<span style="color:#cd0000;">)]</span> <span style="color:#cd0000;">[</span>fa-tail <span style="color:#cd0000;">()])</span>
    <span style="color:#cd0000;">(</span><span style="font-weight:bold;">if</span> <span style="color:#cd0000;">(</span>null? list-regexp<span style="color:#cd0000;">)</span>
        <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span>
        <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> <span style="color:#cd0000;">([</span>head <span style="color:#cd0000;">(</span>car list-regexp<span style="color:#cd0000;">)]</span> <span style="color:#cd0000;">[</span>tail <span style="color:#cd0000;">(</span>cdr list-regexp<span style="color:#cd0000;">)])</span>
          <span style="color:#cd0000;">(</span><span style="font-weight:bold;">cond</span>
           <span style="color:#008b8b;">;; Star closure
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\*</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>char? <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'star</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Kleene closure
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\+</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>char? <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>car fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'star</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Optional presence
</span>           <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>eq? head <span style="color:#008b00;">#\?</span><span style="color:#cd0000;">)</span>
                 <span style="color:#cd0000;">(</span>not <span style="color:#cd0000;">(</span>null? fa-tail<span style="color:#cd0000;">)))</span>
            <span style="color:#cd0000;">(</span>loop tail fa <span style="color:#cd0000;">(</span>list <span style="color:#cd0000;">(</span>cons <span style="color:#008b00;">'opt</span> fa-tail<span style="color:#cd0000;">)))]</span>
           <span style="color:#008b8b;">;; Match-all character
</span>           <span style="color:#cd0000;">[(</span>eq? head <span style="color:#008b00;">#\.</span><span style="color:#cd0000;">)</span>
            <span style="color:#cd0000;">(</span>loop tail <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>list <span style="color:#008b00;">'any</span><span style="color:#cd0000;">))]</span>
           <span style="color:#cd0000;">[</span><span style="font-weight:bold;">else</span>
            <span style="color:#cd0000;">(</span>loop tail <span style="color:#cd0000;">(</span>append fa fa-tail<span style="color:#cd0000;">)</span> <span style="color:#cd0000;">(</span>list head<span style="color:#cd0000;">))]</span>
           <span style="color:#cd0000;">)))))</span>
</pre>
<p>Fungsi <code>build-regexp-matcher</code> mengembalikan fungsi validasi string. Selama fungsi validasi tersebut digunakan, selama itu pula struktur data pola regular diperlukan.</p>
<h2>Teknik #2: Pembangkitan Statis</h2>
<p class="first">Teknik seperti ini, kurang-lebih, yang digunakan oleh pembangkit penganalisa leksikal baik yang memakai switch (e.g. re2c) atau tabel DFA (e.g. flex) untuk mengubah keadaan automaton. Fungsi berikut menyediakan fasilitas serupa:</p>
<pre class="src">
<span style="color:#cd0000;">(</span><span style="font-weight:bold;">define</span> <span style="color:#cd0000;">(</span><span style="color:#0000ff;font-weight:bold;">generate-regexp-matcher-c-code</span> regexp<span style="color:#cd0000;">)</span>
  <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> <span style="color:#cd0000;">([</span>pattern <span style="color:#cd0000;">(</span>build-regexp-list-pattern <span style="color:#cd0000;">(</span>string-&gt;list regexp<span style="color:#cd0000;">))]</span>
        <span style="color:#cd0000;">[</span>echo <span style="color:#cd0000;">(</span><span style="font-weight:bold;">lambda</span> <span style="color:#cd0000;">(</span>level fmt . vals<span style="color:#cd0000;">)</span>
                <span style="color:#cd0000;">(</span>display <span style="color:#cd0000;">(</span>format <span style="color:#008b00;">"~a~a\n"</span>
                                 <span style="color:#cd0000;">(</span>make-string <span style="color:#cd0000;">(</span>* level <span style="color:#008b00;">3</span><span style="color:#cd0000;">)</span> <span style="color:#008b00;">#\space</span><span style="color:#cd0000;">)</span>
                                 <span style="color:#cd0000;">(</span>apply format fmt vals<span style="color:#cd0000;">))))])</span>
    <span style="color:#cd0000;">(</span>echo <span style="color:#008b00;">0</span> <span style="color:#008b00;">"int match( char* cstr ) {"</span><span style="color:#cd0000;">)</span>
    <span style="color:#cd0000;">(</span>echo <span style="color:#008b00;">1</span> <span style="color:#008b00;">"char* c = cstr;"</span><span style="color:#cd0000;">)</span>
    <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> recurse <span style="color:#cd0000;">([</span>pattern pattern<span style="color:#cd0000;">]</span> <span style="color:#cd0000;">[</span>level <span style="color:#008b00;">1</span><span style="color:#cd0000;">])</span>
      <span style="color:#cd0000;">(</span><span style="font-weight:bold;">if</span> <span style="color:#cd0000;">(</span>null? pattern<span style="color:#cd0000;">)</span>
          <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"return 1;"</span><span style="color:#cd0000;">)</span>
          <span style="color:#cd0000;">(</span><span style="font-weight:bold;">let</span> <span style="color:#cd0000;">([</span>head <span style="color:#cd0000;">(</span>car pattern<span style="color:#cd0000;">)]</span> <span style="color:#cd0000;">[</span>tail <span style="color:#cd0000;">(</span>cdr pattern<span style="color:#cd0000;">)])</span>
            <span style="color:#cd0000;">(</span><span style="font-weight:bold;">cond</span>
             <span style="color:#008b8b;">;; Star closure
</span>             <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>list? head<span style="color:#cd0000;">)</span>
                   <span style="color:#cd0000;">(</span>eq? <span style="color:#cd0000;">(</span>car head<span style="color:#cd0000;">)</span> <span style="color:#008b00;">'star</span><span style="color:#cd0000;">))</span>
              <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"while( c &amp;&amp; *c == '~a' ) ++c;"</span> <span style="color:#cd0000;">(</span>cadr head<span style="color:#cd0000;">))</span>
              <span style="color:#cd0000;">(</span>recurse tail level<span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">]</span>
             <span style="color:#008b8b;">;; Optional presence
</span>             <span style="color:#cd0000;">[(</span><span style="font-weight:bold;">and</span> <span style="color:#cd0000;">(</span>list? head<span style="color:#cd0000;">)</span>
                   <span style="color:#cd0000;">(</span>eq? <span style="color:#cd0000;">(</span>car head<span style="color:#cd0000;">)</span> <span style="color:#008b00;">'opt</span><span style="color:#cd0000;">))</span>
              <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"if( c &amp;&amp; *c == '~a' ) ++c;"</span> <span style="color:#cd0000;">(</span>cadr head<span style="color:#cd0000;">))</span>
              <span style="color:#cd0000;">(</span>recurse tail level<span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">]</span>
             <span style="color:#008b8b;">;; Match-all character
</span>             <span style="color:#cd0000;">[(</span>eq? head <span style="color:#008b00;">'any</span><span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"++c;"</span><span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">(</span>recurse tail level<span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">]</span>
             <span style="color:#cd0000;">[</span><span style="font-weight:bold;">else</span>
              <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"if( c &amp;&amp; *c == '~a' ) {"</span> head<span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">(</span>echo <span style="color:#cd0000;">(</span>1+ level<span style="color:#cd0000;">)</span> <span style="color:#008b00;">"++c;"</span><span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">(</span>recurse tail <span style="color:#cd0000;">(</span>+ level <span style="color:#008b00;">1</span><span style="color:#cd0000;">))</span>
              <span style="color:#cd0000;">(</span>echo level <span style="color:#008b00;">"}"</span><span style="color:#cd0000;">)</span>
              <span style="color:#cd0000;">]</span>
             <span style="color:#cd0000;">))</span>
          <span style="color:#cd0000;">))</span>
    <span style="color:#cd0000;">(</span>echo <span style="color:#008b00;">1</span> <span style="color:#008b00;">"return 0;"</span><span style="color:#cd0000;">)</span>
    <span style="color:#cd0000;">(</span>echo <span style="color:#008b00;">0</span> <span style="color:#008b00;">"}"</span><span style="color:#cd0000;">)))</span>
</pre>
<p>Pada dasarnya teknik pembangkitan statis ini memanfaatkan informasi tentang pola-pola lexeme yang dinantikan, dan mengkodekan informasi tersebut dalam program. Pemanfaatan informasi seperti ini lazim disebut sebagai <a href="http://c2.com/cgi/wiki?PartialEvaluation">evaluasi parsial</a>, yang tujuannya tidak lain adalah optimasi program. Bila kita tahu program kita (translator atau interpreter) hanya akan menerima input dalam bahasa tertentu, kenapa harus repot-repot mengakomodasi input di luar bahasa tersebut?</p>
<h2>Evaluasi Parsial Untuk Kemudahan Pengelolaan</h2>
<p class="first">Awalnya saya mau bilang, dari sudut pandang pemrogram translator, perbedaan kedua teknik di atas adalah pada efisiensi. Logika dasarnya begini: dengan pembangkit scanner, string ekspresi regular diubah menjadi kode, bagian dari program translator. Setiap kali program dijalankan, pola yang akan dicari telah tersedia, menyatu dengan alur komputasi program. Berbeda dengan pustaka regex, di mana string ekspresi regular dimuat dalam citra biner translator dan dibaca untuk membangkitkan struktur data pola, setiap kali translator (atau kalau pemrogramnya masih awam, fungsi scanner) dijalankan.</p>
<p>Secara intuitif, kita bisa yakin bahwa pembangkitan statis lebih cepat ketimbang pembangkitan dinamis karena tidak memerlukan alokasi dan dealokasi struktur data dinamis, serta dereferensi pointer. Pertanyaannya adalah: seberapa signifikan peningkatan kecepatan tersebut? Saat akan menulis dan menguji contoh, saya terbentur satu fakta: rata-rata komputer sekarang sudah sedemikian cepatnya, perbedaan kecepatan antara pengenal bahasa yang menggunakan pustaka regex generik dan pembangkit scanner baru terasa bila dipanggil <em>500 ribu kali</em> secara beruntun<sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup>. Memangnya ada program pengenal bahasa yang pola penggunaannya seperti itu?</p>
<p>Konsekuensinya, salah satu pokok opini awal saya sebelum menulis catatan ini, &quot;untuk merakit scanner, selalu gunakan pembangkit scanner&quot;, gugur dengan sendirinya (meski judulnya dipertahankan, karena tidak terlalu menyimpang dari fakta, <em>catchy</em>, dan saya suka peran Russell Crowe di <a href="http://www.imdb.com/title/tt0114214/">film ini</a>). Saat akan menciptakan sebuah program, seseorang bebas menggunakan perangkat apapun yang ia rasa paling tepat. Bila perakitan scanner menggunakan pustaka regex lebih mudah baginya, terserah! Asalkan ia tahu semua alternatif, serta kelebihan dan kekurangan masing-masing.</p>
<p>Namun pokok opini kedua saya rasanya tetap valid, sejalan dengan catatan sebelumnya: Evaluasi parsial membuat kompleksitas program jauh lebih mudah ditangani pemrogram. Pembangkit scanner yang baik tidak selalu lebih efisien dari perakitan scanner secara manual, tapi ia selalu lebih mudah dikelola. Sebagai contoh, meski saya bilang kode ini jauh dari ideal, analisa leksikal dalam prototip kompiler Jeruk<sup><a class="footref" name="fnr.3" href="#fn.3">3</a></sup> dilakukan oleh satu fungsi berikut (memakai re2c):</p>
<pre class="src">
<span style="color:#bc8f8f;">/**
 * Melakukan analisa leksikal pada file input, mengisi buffer bila
 * diperlukan
 *
 * \param lexer scanner
 *
 * \return Nilai enumerasi tipe token
 */</span>
<span style="color:#228b22;">int</span> <span style="color:#0000ff;">lexer_scan</span>( <span style="color:#228b22;">void</span> *<span style="color:#b8860b;">lexer</span> ) {
  <span style="color:#228b22;">Lexer</span> *<span style="color:#b8860b;">l</span> = (<span style="color:#228b22;">Lexer</span>*) lexer;
  <span style="color:#228b22;">int</span> <span style="color:#b8860b;">level_komentar</span> = 0;
 <span style="color:#5f9ea0;">standar</span>:
  l-&gt;token = l-&gt;cursor;
  <span style="color:#b22222;">/*</span><span style="color:#b22222;">!re2c
    digit* "." digit+
    { goto akhiran_float; }
    digit+ "." digit*
    { goto akhiran_float; }
    digit+
    { RET( tk_INTEGER ); }

    huruf (huruf|digit|[_])*
    { RET( keyword_chk( lexer_cstr(l) ); ); }

    ["]
    { goto uniline_string; }

    ["]{3}
    { goto multiline_string; }

    "+" { RET( tk_PLUS ); }
    "-" { RET( tk_MINUS ); }
    "*" { RET( tk_MULT ); }
    "/" { RET( tk_DIV ); }

    "(" { RET( tk_LPAREN ); }
    ")" { RET( tk_RPAREN ); }
    "{" { RET( tk_LCBRACKET ); }
    "}" { RET( tk_RCBRACKET ); }
    "[" { RET( tk_LSBRACKET ); }
    "]" { RET( tk_RSBRACKET ); }

    "&lt;"  { RET( tk_LT ); }
    "&gt;"  { RET( tk_GT ); }
    "&lt;=" { RET( tk_LEQ ); }
    "&gt;=" { RET( tk_GEQ ); }
    "="  { RET( tk_EQ ); }
    "!=" { RET( tk_NEQ ); }

    "&amp;" { RET( tk_AND ); }
    "|" { RET( tk_OR ); }

    ":=" { RET( tk_ASSIGNMENT ); }

    ";" { RET( tk_SEMICOLON ); }
    "," { RET( tk_COMMA ); }

    '\r'?'\n'
    { if( l-&gt;cursor &gt;= l-&gt;eof )
      { RET( tk_EOI ); }
      l-&gt;last_nl = l-&gt;cursor;
      ++l-&gt;line_num;
      l-&gt;token = l-&gt;cursor; goto standar;
    }

    spasi+ { l-&gt;token = l-&gt;cursor; goto standar; }

    "//" { while( *l-&gt;cursor != '\n' ) ++l-&gt;cursor; goto standar; }

    "\/*" { ++level_komentar; goto komentar; }

    [^]
    { @@error( "Karakter tidak dikenali, \'\\%.3d\' = \'%c\'",
               l-&gt;token[0], l-&gt;token[0] )
    }

   </span><span style="color:#b22222;">*/</span>
 <span style="color:#5f9ea0;">akhiran_float</span>:
  <span style="color:#b22222;">/*</span><span style="color:#b22222;">!re2c
    ( [Ee] [+-]? digit+ )?
    { RET( tk_FLOAT ); }

    '\r'?'\n'
    { if( l-&gt;cursor &gt;= l-&gt;eof )
      { RET( tk_EOI ); }
      l-&gt;last_nl = l-&gt;cursor;
      ++l-&gt;line_num;
      l-&gt;token = l-&gt;cursor; goto standar;
    }
   </span><span style="color:#b22222;">*/</span>
 <span style="color:#5f9ea0;">uniline_string</span>:
  <span style="color:#b22222;">/*</span><span style="color:#b22222;">!re2c
    ["]
    { RET( tk_STRING ); }

    [^]
    { goto uniline_string;
    }

    '\r'?'\n'
    { @@error("String tidak ditutup"); }
   </span><span style="color:#b22222;">*/</span>
 <span style="color:#5f9ea0;">multiline_string</span>:
  <span style="color:#b22222;">/*</span><span style="color:#b22222;">!re2c
    ["]{3}
    { RET( tk_STRING ); }

    [^]
    { goto multiline_string;
    }

    '\r'?'\n'
    { if( l-&gt;cursor == l-&gt;eof )
      { @@error("String baris-jamak tidak ditutup"); }
      goto multiline_string;
    }
    </span><span style="color:#b22222;">*/</span>
 <span style="color:#5f9ea0;">komentar</span>:
  <span style="color:#b22222;">/*</span><span style="color:#b22222;">!re2c
    "\/*" { ++level_komentar; goto komentar; }

    "*\/"
    { --level_komentar; if( level_komentar == 0 ) goto standar; }

    '\r'?'\n'
    { if( l-&gt;cursor == l-&gt;eof )
      { @@error("Baris komentar tidak ditutup"); }
      l-&gt;last_nl = l-&gt;cursor;
      ++l-&gt;line_num; goto komentar;
    }

    [^] { goto komentar; }
   </span><span style="color:#b22222;">*/</span>
  RET( tk_EOI );
}
</pre>
<p>&#8230; dan satu fungsi tambahan <code>keyword_chk</code> untuk membedakan keyword dari identifier menggunakan tabel hash. Seandainyapun diiming-imingi imbalan agar menggunakan cara lain, saya tetap lebih memilih teknik pembangkitan statis seperti di atas. Mudah dibaca, dipahami, diubah dan dikembangkan.</p>
<hr />
<p class="footnote"><a class="footnum" name="fn.1" href="#fnr.1">1.</a>  Grammar mempunyai dua fungsi: sebagai perangkat pembangkit (generator) dan pengenal (akseptor) kalimat.</p>
<p class="footnote"><a class="footnum" name="fn.2" href="#fnr.2">2.</a>  Teknik prefetching Windows memungkinkan eksekusi program untuk kali kedua dan seterusnya lebih cepat dari yang pertama.</p>
<p class="footnote"><a class="footnum" name="fn.3" href="#fnr.3">3.</a>  Saya mengembangkan sendiri kompiler ini di waktu senggang, membuatnya sering terbengkalai.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/dajak.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/dajak.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/dajak.wordpress.com/50/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dajak.wordpress.com&amp;blog=4237658&amp;post=50&amp;subd=dajak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://dajak.wordpress.com/2009/01/21/dua-cara-merakit-scanner-menggunakan-regex/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cbe5c58a8154ae278d59048a7acfdf2b?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">adhi</media:title>
		</media:content>

		<media:content url="http://dajak.files.wordpress.com/2009/01/mesin_regular.jpg" medium="image">
			<media:title type="html">mesin_regular</media:title>
		</media:content>
	</item>
	</channel>
</rss>
