Emacsが好きだからS式のパーサー書いた

今思うとちょっとどうかしていたと思うけど、
S式しか返さないHTTPサーバーを作って、Emacsからしか読めないWebサービスを作ろうという計画が僕の胸の内にあったため、
その計画の第一歩として、S式のパーサーを書いてみたのだった。
これはサーバーをnode.jsで作ろうとしていたので、jsで書いた。

https://github.com/f-kubotar/sexpression

S式をjsのどんなデータ構造に割り当てていくかは、色々な形が考えられると思うけど、結果的に以下のようにした。

  • リスト -> Array
  • シンボル -> nameというプロパティを持つオブジェクト
  • コンスセル -> car,cdr という2つのプロパティを持つオブジェクト
  • キーワードリスト (:key val :key val)みたいな。 -> Object (連想配列)

一応、S式 <-> js の相互変換ができるようにはなってる。(はず)

リスト

リストをArrayに変換するのは当たり前じゃん。と直感的には思っちゃうけど、
S式のリストというのは、配列ではなくて、ネストしたコンスセルなので、
たとえば、コンスセルをjsで

{ car: 1, cdr: 2}

と表現するとすると、
(1 2 3) というリストは、S式の実装としては、

{ car: 1, cdr: { car: 2, cdr: { car: 3, cdr: null } } }

と表現するのが正しいとおもう。
でもこんなことすると、数字添字とかループとか自前で実装しないといけないからちょっと不便だし、
効率が悪そうだから、一回実装してみたものの、やめてしまった。

連想配列

S式では連想配列っぽいものの表現が複数ある。

alist (コンスセルのリスト)
((a . 1) (b . 2))
ハッシュ

make-hashとかで作ったりするやつ。

klist キーワードリスト

:ではじまるシンボル(キーワードシンボル)と値が対になったふつうのリスト

(:a 1 :b 2)

ハッシュはちょっとリストとして表現するのがめんどくさかったので存在を無視した。
Elisp上だと、alistの方が、操作する関数が多くて扱いやすかったりするけど、
データとして扱うのはklistがお手軽だったので、klistにした。
(alistをObjectに変換するのも一応実装してみた)
キーワードリスト以外の目的でキーワードシンボルを使うことが皆無だとおもうので、
壊れた連想配列を作ってしまったりする可能性は、alistもklistも対してかわんないかなとおもって