「48時間でSchemeを書こう/構文解析」の版間の差分

削除された内容 追加された内容
M編集の要約なし
1 行
== 簡単なパーサ ==
 
では、非常に簡単なパーサを書いてみましょう。それには[http://www.haskell.org/ghc GHC]に付いてくる[http://www.cs.uu.nl/~daan/download/parsec/parsec.html Parsec]ライブラリ(Ubuntuではlibghc6-parsec-devパッケージをインストール)を使いますが、他。GHC以外のコンパイラを使っている場合は別にダウンロードする必要があるかもしれません。
 
まずは次の行をimportセクションファイルの冒頭に加えてください。
 
<syntaxhighlight lang="haskell">
9 行
</syntaxhighlight>
 
これによって、私たちParsecのライブラリ関数後に定義す使えことようになる関数と名前が衝突りま<code>spaces</code>関数以外は後で自分で定義するで、Parsecで定義されている同名ライブラリ関数を使えるインポートしないようになります。
 
では、Schemeの識別子中に許される記号一つを認識するパーサを定義します。
 
<syntaxhighlight lang="haskell">
18 行
</syntaxhighlight>
 
これもモナドの一例です。この場合、隠蔽された「追加情報」は入力ストリーム、バックトラックの記録、ファーストfirstフォローfollow集合などの全てのに関する情報です。それらは全てParsecが取り扱ってくれます。私たちはParsecのライブラリ関数を使うだけでよいのです。[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#oneOf oneOf]を使うだけでよく、それは引数で与えられた文字列中のどれか一文字を認識します。Parsecはいくつもの既成のパーサを提供します。例えば、[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#letter letter][http://www.cs.uu.nl/~daan/download/parsec/parsec.html#digit digit]はライブラリ関数でなど、いくつものこまごまとした既成のパーサを提供します。そしてこれから見ていくように、これらの基本的なパーサを使ってより洗練された複雑なパーサを組み立てていくことができます。
 
上で定義しちの<code>symbol</code>パーサを呼び出し、起こり得るエラーが発生したらそれを処理する関数を定義しましょう。
 
<syntaxhighlight lang="haskell">
31 行
型宣言からわかるように、<code>readExpr</code>は文字列から文字列への関数(<code>-></code>)です。<code>input</code>という引数を取り、それと共に上で定義した<code>symbol</code>アクションと、作ったパーサの名前(<code>"lisp"</code>)をParsecの[http://www.cs.uu.nl/~daan/download/parsec/parsec.html#parse parse]関数に渡します。
 
<code>parse</code>はパースした結果の値かエラーを返すので、エラーの場合も扱わなければなりません。Haskellの典型一般的な慣習にって、Parsecは[http://www.haskell.org/onlinereport/standard-prelude.html#$tEither Either]データ型を返します。<code>Left</code>構築子でエラーを、<code>Right</code>で通常の値を表します。
 
<code>parse</code>の結果をこれらの選択に対してマッチさせるには<code>case...of</code>構文を使います。もし<code>Left</code>の値(エラー)を得たら、そのエラーを<code>err</code>に束縛し、エラーの文字列表現と共に<code>"No match"</code>を返します。もし<code>Right</code>の値を得たら、それを<code>val</code>に束縛しますが無視して、文字列<code>"Found value"</code>を返します。
 
<code>case...of</code>は[[#Evaluation, Part 1|後に]]もっと全然詳しく見ることになるパターン・マッチの一例です。
 
最後に、<code>readExpr</code>を呼び、結果を出力するように<code>main</code>関数を変更しなければいけません(ファイルの頭に<code>import System</code>も追加しましょう)。
48 行
これをコンパイル・実行するには、正常にリンクさせるため、コマンドラインで<code>-package parsec</code>を指定します。
 
<syntaxhighlight lang="bashtext">
% ghc -package parsec -o simple_parser simple-parser.hs
% ./simple_parser $