ML用のCSV読み込みライブラリを作りました。ML単純な使い方はテストケースを見るとすぐわかると思います。ML用のXMLパーサーを作った。UXMLSMLの世界にはSMLで書かれたXMLパーサーが(知っている範囲では)すでに2つある。1つはSMLNJ-LIBの中にあるXMLストラクチャで、これはかなり非力なものだ。UXMLは非検証のXMLプロセッサーとしてXML1.0になるべく準拠しようとしている。非準拠であるが、現実的な処理では十分に使える状態になっていると思う。名前空間をサポートしている点と、XPathライクなナビゲーションAPIを持つ点がある。使用するにはタグv.0.1.0を取得するか、Smackageから利用してほしい。git://github.com/tkob/uxml.gitという行を追加し、SML/NJのCMファイルからは`$SMACKAGE/uxml/v0.1.0/uxml.cmのように参照する。MLからZIPファイルの読み込み・解凍をするためのライブラリを作った。https://github.com/tkob/smlzip特徴はPure-SMLである(Cバインディングではない)という点である。機能は読み込みのみで、現状は最低限のことができる程度だ。異なるMLB/CMを選択できるようになっている。利用できるようにするためのファイルも配置してみた。バグ等をみつけたらGithubのissueに報告してほしい。[SML]SML用のパーサジェネレータProglrの最近の進展について。これまでは字句解析は自分で書く必要があった。凝った字句解析をしない場合はやはり自動で生成してくれるのが便利だ。いうわけで文法定義からml-ulexのソースを自動生成する機能をつけた。指定された文字列のトークンを字句解析にも追加する。ような定義があった場合はそれぞれのリテラルのトークンを追加する。これにより簡単な言語を作る場合はml-ulexのソースをまったく書かなくてもよくなる。example/calc/calc.cfというサンプルがあるのでそれを参照してほしい。同様にコメントについても字句解析に自動追加できるようになった。下記のような定義でそれぞれブロックコメントと行コメントを追加できる。これはBNFCと同様である。各ML処理系でビルドするためのドライバ、Makefileなども自動生成するようにした。ml-lptランタイムのソースも展開されるようにした。これにより基本的には文法定義ファイルだけから実行可能ファイルを作るまでのすべてが生成可能となった。数行のコマンドラインでサンプルプロジェクトがビルドできるようになっている。起動方法はREADMEを参照してほしい。MLtonとPoly/MLに注力することにした。SML#向けのファイルも残っているが、動かないものと思ってほしい。リンクに関してはまだあまりわかっていない。これは依存する.alcがしかるべき位置に配置されていればそのまま実行できる。依存性のエラーが出てしまう。このためREADMEではリンクせずに実行するような手順を書いている。文法定義から作られるオートマトンを視覚化するためのdotファイルを生成できるようにした。いうオプションを与えると生成できる。依存するツールProglrが依存している外部ツールを挙げる。利用できないということはないと思う。[SML]SMLの処理系のC言語インターフェイスをCのヘッダから自動生成するツールを作った。Generator現在のところMLtonとPoly/MLに対応していて、cursesを使うサンプルが動くようになっている。先行するものとしてSML/NJとMLtonにはmlnlffigenというツールがあるようなのだけど、使い方がよくわからなかったのだ。やりたいのはCの関数の型をMLの型に書き換える機械的な作業なので、いいや自分で作ろうということになった。C言語の構文解析には紆余曲折の後libclangをPythonから使うことにした。Ubuntuでpython-clang-3.3を導入した環境で動作を確認している。一般的な構文解析ツールでC言語の構文解析をしようとするとtypedef問題などに突き当たってしまって、かなり面倒なことになる。libclangは何と言ってもCコンパイラが使う真正のC言語パーサーだからそれを使えるのは理想的なはずだ。libclang自体の使い方もドキュメントが乏しくてよくわからないところが多い。面倒くささということに関しては結局どっちもどっちかもしれない。MLの文法について調べていて気付いたこと。Identifiers)。(syntacticなカテゴリではなく)lexicalなitemであるとしている。するとこのドットの前後にホワイトスペースは許容されるのかという疑問が生じてくる。ホワイトスペースをトークン中に含まない。いえそういうことができないわけではない。一方でプログラミング言語一般的にはドットの前後で改行できるのが普通だと思う。各種のSML実装で比較してみると、なんと!許容しないほうが多数派だった。定義されていることにも気づいてしまった。[SML]ちまちま作っていたSML用のパーサージェネレーターが結構形になってきたので紹介します。https://github.com/tkob/proglr先日の記事ではML-BNFCという名前で、パーサーはLR(0)の状態だった。Logothetisの方法なるものを使ってLALR(1)にするということを考えていたんだけど、面倒に思えてきたのと、そのわりに得られる結果がLALR(1)で独自性がない気がしたので結局GLRにした。するとこのパーサージェネレーターの独自性はどちらかというとGLRになるのでML-BNFCという名前もやめてML-GLRという名前にした。いまでは文法定義ファイルからSMLソースを生成するようになっていて、文法定義ファイルの解析自体もML-GLR自身が生成したものになっている。ML-GLRっていう名前のパーサージェネレーターが既にあった!http://www.cis.uni-muenchen.de/~leiss/relationaleGrammatik-09-10/ml-glr.pdfということでさらに名称変更してProglrという名前にした。Makefile.mltonパターンマッチに関する警告がたくさん出ますが無視してください。proglrという実行ファイルができます。MLtonのほかに一応MLKitとPoly/MLでもビルドできるようになっています。BNFCにおおむね似ている。;この文法定義からは次のようなAST型が生成される。endスキャナーの定義はml-ulexを使う。());ドライバとなるプログラムは次のような感じで書く。()ビルドするときはランタイムとしてsmlnj-libとmllpt-libをリンクする。[SML]SMLのためのLRパーサージェネレーターを新しく自分で作っている。限定的なことしかできないしコードが汚い部分も残っているのだけど、公開された場所に置くことがモチベーションになるかもしれないと思ってGithubにアップロードした。新しくパーサージェネレーターを作るということ―車輪の再発明―を正当化するのはなかなか難しい。私の場合は、自分で好きなように手を入れられるものが欲しいと思った、という程度ものだ。新しく作るからには既存のものと少しは違う。作るにあたっての方針と、今後の目標を次に記そうと思う。方針ml-ulexと組み合わせて使えるSML/NJには歴史のあるml-yacc/ml-lexに加えて、ml-lptという言語処理系作成向けのツール群がある。ml-ulexはml-lptに付属するスキャナージェネレーターである。これはml-lexに比べると非常に進化していて、どうしてもこれを使いたかった。ml-lptを使えば使えるのだが、基本的にはml-antlrというLL(k)のパーサージェネレーターと組み合わせるしかなかった。構文木のデータ型を自動生成するパーサージェネレーターには普通セマンティックアクションを付与した文法定義を与え、そのセマンティックアクションの中で構文木の生成を行うという形をとることが多い。多いというか、パーサージェネレーターを使う殆どのケースでまずは構文木を作ると思う。したらパーサージェネレーターが構文木のデータ型も構文木を構築するコードも自動生成してくれればいい。以前紹介したBNFCがそのような機能を提供していてとても便利だと思っていたのでそれを取り入れた。ツールの名前もそこからとってML-BNFCとした。生成されるコードはできるだけ多くのSML処理系で動くようにする。現時点でコミットしてあるコードはブートストラップしていなくて、文法定義はSMLのデータとして直接与えて一緒にコンパイルするしかない。ビルドするとmlbnfcというバイナリができ、ファイル名を与えて実行するとパーサーおよび構文木のデータ型のコードを出力する。このコードはml-ulexで書いたスキャナーを組み合わせて使えるようになっていて、パースすると構文木が作られる。文法定義を外部ファイルから読み込むようにする雛形となるようなドライバのコードも自動生成するようにしたい現在LR(0)の文法しかサポートされていない。Libraryをどこまでサポートしているかを比較してみたいことがある。自分だけかもしれないが、そういう一覧が必要だと思ったので作ることにした。いえ数多いモジュールとそれに属する関数や定数をいちいち手作業で確かめるのは大変なのでスクリプトを書いた。個別のモジュールの解説ページのURLを取得してmanpages.txtに保存する。module.rbがそれらのページからstructureとそれに属する値を抽出する。ここでInt{N}とかWord{N}のようなstructureは16,31,32,63,64の値で展開することにした。この結果がval.txtに保存される。これは「Array.length」のような名前が1行1つの形式である。REPLのある処理系ならばREPLに打ち込んで評価させればよい。これをそのまま行うためExpectを使ってREPLを制御することにした。check.tclがそれを行う。poly.txtなどの名前で結果が保存される。compare.rbが処理系ごとの結果を列として読み込んで横に並べ変える。(この種の処理をしたくなることは多いのだけどいつもコードをたくさん書いている気がする。最後にperlのワンライナーでMarkdown形式に変換する。して得られたのが次の結果である。結果https://gist.github.com/tkob/11498120MLtonやMLKitのようなREPLのない処理系はいまのところ未対応である。やるとしたらautoconf系のツールで行われているように短いプログラムをコンパイルさせてコンパイルが通るかどうかを見る方法になるだろう。これは64bit版のUbuntuで得られた結果だが、32bit環境などではInt{N}などのサポート状況は変化するだろう。[SML]SML用のMessagePack実装を作りました。これらすべてでコンパイルが通るようにしてありますが、テストケースが無傷で通るのは最初の3つだけで、他は処理系側で機能に制限があったりバグがあったりします。SML#は大半のテストが通りません。SML#1.2.0ではテストが通りませんでしたがSML#2.0.0では通るようになりましたので、SML#を使う場合は2.0.0以上をお使いください。扱いたいデータ型に対するpacker/unpackerを基本的なコンビネーターを組み合わせて作ります。BytesIO.instream詳しくは同梱のTUTORIAL.mdを参照してください。別のSMLプロジェクトで、データをマーシャルして流すようにしたいとおもい、フォーマットとしてはMessagePackに目を付けました。いうものがすでに存在することが分かったのですが、少し使ってみたところこれは事実上MLton専用で、移植も簡単にはいかないということがわかったので、結局自分で作ることにしました。移植性というのをコンセプトの1つにしたので各種処理系でテストしながら作っていたのですが途中からSML処理系自体に対するテストみたいになってしまった。あといざ実装してみるとMessagePackの仕様自体にも多少不満があって、もうちょっと明示的に書いてほしいところが足りてなくて迷うときがあった。これについては時間があれば別の機会に書きたい。(..単体テストのための外部DSLカテゴリーOCaml(62)Tcl(27)D言語(5)COM(1)PowerShell(9)JavaScript(5)Linux(2)Lua(19)XSLT(1)Lisp(32)Excel(2)コードリーディング(4)Ruby(9)言語比較(7)Haskell(6)Groovy(1)PHP(10)Scala(48)Perl(2)Erlang(4)Python(2)Prolog(8)Java(8)自然言語(1)awk(1)SML(19)sh(2)SMV(1)YokohamaUnit(8)Rehearsal(1)Isabelle(1)最近のコメント不本意というよりは意外、というのが..ご案内ありがとうございます。..ご紹介&コメントありがとうございま..OCaml3.11のCamlp4か..エラー出た時はここが参考になりまし..コメントありがとうございます。SML#のバグ報..コメントありがとうございます。ソネットポイントこの広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。この広告は180日新規投稿のないブログに表示されます。