komorebikoboshiのブログ

プログラミング記事(趣味レベル)が多め。

VS2013でFsYacc、FsLexを使う

Visual Studio 2013*1でFsYaccとFsLexを使うには、基本的に
http://stackoverflow.com/questions/19781156/using-fslex-yacc-in-vs2013
の通りにすればいいのですが、2つほどハマったところがあったのでそれを書いておきます。

FsYacc、FsLexが参照するFSharp.Coreのバージョン

VS2013 + F# 3.1.1しかパソコンにインストールしていない場合、FsYaccやFsLexが起動しません。これはそれらのツールがFSarp.Core.dllのバージョン3.0を読みに行こうとしているのが原因です。
そこで、F#のコンパイラFsc.exe)のあるディレクトリ*2にある「○○.exe.config」というファイルを2つぐらい、プロジェクトのfslex.exeやfsyacc.exeがあるディレクトリにコピーして、それぞれ「fslex.exe.config」「fsyacc.exe.config」とリネームします。これでFsYaccやFsLexはFSarp.Core.dllのバージョン3.1.1を読み込んでくれるようになります。

ファイルの更新順序

今回FsYaccの使い方についてfslexとfsyaccを使って字句・構文解析して電卓っぽい計算をしてくれる奴を作成したい - My Life as a Mock Quantを参考にさせてもらったのですが、この記事の例を試す時に

  1. Lexer.fslを追加して編集
  2. Parser.fsyを追加して編集
  3. Parser.fs、Lexer.fsを追加
  4. .fsprojファイルをいじる
  5. ビルド

の順番に作業するとうまくいきません。(FsLex、FsYaccが走らない)理由は、Lexer.fsやParser.fsをLexer.fslやParser.fsyより後に作成している(つまり、より新しい)ため、MsBuildが更新の必要がないとしてFsLexなどのタスクをスキップするためです。(結果、Parser.fsなどの中身が作成されない)
これを回避するには、まあ、Parser.fs、Lexer.fsをLexer.fslやParser.fsyよりも先に追加しておくとか、.fslや.fsyに適当なコメントとかを書いて更新時間を遅くする、とか。おそらく初回のビルド以降では問題にはならないでしょう。
なお、これはMsBuildコンパイルタスク*3を使うときに問題になりますが、Pre-build eventで直接fslex.exeなどをたたく方法の時は関係ありません*4

まとめ

  • FsYaccなどが参照するdllを~.exe.configでごまかす
  • ファイルの更新時間に気を付ける。.fsyや.fslの方を新しくする

*1:私が使っているのはExpress + Visual F# tool 3.1.1です

*2:私のパソコンだと C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0

*3:最初のstackoverflow.comの記事に書いてあった方法

*4:更新時間にかかわらず毎回ツールが実行される