M Grammer で C++ をパース

4/6 の Tech Fielders セミナーに向けて Oslo 予習中。

で、M Grammer で C++ をパースする文法定義を書いてみた(みてる最中)。

  • C++ のヘッダーを一番のデータソースにしたい人がいつまでたってもいなくならない
  • しょうがないから C++ ヘッダーをパースして型定義を抜き出すコードを書きたい
  • ということで、M Grammer で C++ パースできるようにしてみた
  • 「そんなもん公開したらより一層、C++ をデータソースにしたがる人が減らないじゃないか」って叩かれそうorz

まあ、C++ のクラス・構造体のオレオレシリアライザーを自動生成したいときとかに使ってください。

# しかしまあ、M って名前どうにかならないですかね。検索しにくいったらありゃしない。

M言語(コードネーム Oslo)おさらい

リンク

用語のおさらい

  • M: モデリング用の言語
  • Mg(M Grammer): DSL → M 言語ソース生成のための DSL 文法定義言語
    • bison/flexyacc/lex の文法しっかりした版
      • (誰か、bison とかとの比較してくれないかなぁ)
    • 目的がモデル定義用DSLのパースなので、宣言的言語を書く前提
      • でも、C++ をパースできるくらいの能力ちゃんとある
      • もちろん、やろうと思えば C# のパースも可能
        • C# の文法定義が公式に公開されてない理由は「独自の方言が乱立して欲しくないから」らしい

ということで C++ のパース

まだ C++ の文法をフルでサポートはしてないけども、そこそこパースできるようになったので .mg ファイルを公開してみる。

ソースとかサンプルとか

状況

  • 名前空間、クラス(ネスト可能)、メンバー変数、関数定義あたりには対応。
  • 四則演算や比較くらいはできる(new, delete とか、一部の式には未対応)。
  • クラス・構造体をパースしてオレオレシリアライザーを作る程度には対応できそうな感じ。
    • 足りてないと思うのは、template に対応してないあたり。

使い方

まず、mg.exe で mg ファイルのコンパイル。mgx(中間形式、OpenXml? 形式の ZIP)に変換。

PS > $env:Path += ';C:\Program Files\Microsoft Oslo SDK 1.0\Bin'
PS > mg cpp.mg
(cpp.mgx が生成される)

mgx.exe でパース。M形式を出力するかXAMLにするかはオプションで指定。

PS > mgx /reference:cpp.mgx /language:Programming.Cpp test.h
(test.m が生成される)

PS > mgx /reference:cpp.mgx /language:Programming.Cpp test.h /target:Xaml
(test.xaml が生成される)

XAML にしてしまえば、PowerShell とか XML を読み書きする能力持ってる言語から自由に扱えるんで、あとはお好きに。PowerShell マジお勧め。

C# からも使える

Oslo SDK を入れたら .NET 向けライブラリも付いてくる。

C# 向けコード

var parser = DynamicParser.LoadFromMgx(@"cpp.mgx", "CppSample.Cpp");

object root;

using (var cppFile = File.OpenText(@"C:\work\vce\include\vce2serialize.h"))
{
    root = parser.Parse<object>(null, cppFile, ErrorReporter.Standard);
}

// root にさっきの .xaml 相当の構造が入る。

DynamicParser を使うには以下の DLL を参照。

C:\Program Files\Microsoft Oslo SDK 1.0\Bin\System.Dataflow.dll

おまけ(C++ の文法に関して)

C++ の文法に関して参考にしてるのはここ↓
http://cse.csusb.edu/dick/c++std/cd2/gram.html

あと、これやってて初めて知った C++ の文法もあったり。

それと、文法見てるとますます C++ 放棄して C# に完全移行したくなった。

  • 「auto long long int const *const &」ってのが合法って・・・
  • struct { int x; } variableName = { 10 }; とかも勘弁して欲しい。

これをパースするためだけにどれだけ文法定義面倒になるか・・・