良質な睡眠が良質な活動の秘訣だと、体感するようになってきた今日このごろです。最後にここまで、今年1年頑張りたいこと・やりたいことを思いつくままにつらつらと書き連ねましたが、「言うは易く行うは難し」なので、有言実行を心がけます。いまどきどんな言語でも、字句解析器(lexser)と構文解析器(parser)を生成するためのツール(それぞれlexとyaccに準ずるもの)が提供されている場合が多いです。MLの各処理系でも、ML-LexとML-Yaccというツール(名前は各処理系によって違います)が提供されている場合が多いです。これらのツールを使えば、簡単に字句解析器と構文解析器を生成することができます(とは言っても、SMLの場合は日本語の記事が少ないのは間違いありません)。これらのツールを使えばよいのですが、SMLならツールを使わないでも比較的簡単にlexerとparserを書くことができます。今回の記事では、ラムダ計算のためのlexerを書いていこうと思います。この記事では愚直にコードを書いていて、処理効率などは一切考えていません。処理効率などを考えて改良しました!みたいな記事を誰かが書いてくださればうれしいです。字句解析での最小単位となるトークンの定義をします。SMLなら代数的データ型を使って簡単に定義できます。EOF次に、空白文字をとばす処理をする関数skipSpacesを定義します。この関数は、入力ストリームを受け取り、空白文字でない文字にあたるまで入力(空白文字)を捨てます。()入力ストリームを1文字先読みして、その結果をパターンマッチで取り出して処理しています。ある文字が空白文字かどうかは、CharストラクチャのisSpace関数を使えば簡単です。次に、先頭が英字とわかっている入力ストリームから識別子を読み出す関数readIDを定義します。識別子は、英字から始まり、英数字が0個以上続く列とします。end実際の処理は、内部のreadId'関数で行っています。この関数は、識別子(の文字列)strを受け取り、入力ストリームを1文字先読みして英数字ならstrに連結し、そうでないならstrをそのまま返しています。ここまでこれは、あとは字句解析を行うlex関数を定義するだけです(はやい!すごい!簡単!)。lex関数は、入力ストリームを受け取り、トークンを切り出す関数です。end)これまでに書いてきた関数を組み合わせて、パターンマッチをしているだけです。入力ストリームから空白文字を捨て、ストリームの末尾に達していたらEOFトークンを返します。ない場合は1文字読みます(valOfを使っていて危険に見えますが、lookahead関数はストリームがEOFのときにNONEを返すので、今回は必ずSOMEを返し、valOfは失敗しません)。先読み文字が英字の場合は識別子のため、readId関数を使います。ない場合は、1文字読み込んで、バックスラッシュならLAMBDA、左カッコならLPAREN、右カッコならRPAREN、ドットならDOT、それ以外の何かある文字ならSOMETHINGを返します。これだけで、字句解析器が作れます。x1)という文字からなるファイルterm.txtを読み込んでみましょう。lexを何回も読みだせば、確かにトークンが読み出されていると思います。これだけで簡単にlexerを書くことができます。日曜日の次には、必ず月曜日がやってくる。月曜日だからこそ、言うべき言葉がある。「今日も一日がんばるぞい!」*1この言葉で、また一週間がんばれる。これは世界に多くあふれるお話の一つ。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。