2011年8月22日月曜日

Xtextグラマーのポイント(3)

もう少しだけ、Xtextグラマーの面白いポイントを見てみます。
The Grammar Language  から幾つか拾ってみます。

順不同グループ

Modifier:
    static?='static'? & final?='final'? & visibility=Visibility;
どの順で現れても良いが、それぞれの要素は一度の出現しか許容しないという制約は、DSLではよく使いますね。順不同グループは、まさにその時に使う構文で、「&」で候補を区切ります。
選択構文は「|」区切りだったのが、「&」になっただけなので、簡単ですね。
上記の例は、Javaの修飾子指定に似た例ですが、'static'と'final'と可視性(visibility)が、それぞれ順不同で一度だけ現れて良いことを示しています。
この例では、'static'と'final'は「?」がついているのでオプションですが、visibilityは必須修飾子となっていますね。また、staticとfinalは「?=」割当オペレータが使われているのでboolean属性、visibilityは通常の「=」割当オペレータが使われているので、必須属性(または参照)としてモデル化されます。

列挙
enum Visibility:
    PUBLIC='public' | PRIVATE='private' | PROTECTED='protected';
一つの属性の値として現れて良い終端文字列を、いくつかの候補に制約したいことも、DSLでは頻繁にありますよね。その場合に使うのが列挙です。
Xtextでの列挙は、上記のようにまさに「enum」終端ルールとして宣言します。
左辺(PUBLICなど)はモデル上のenum定数名になり、右辺('public'など)はDSL上の終端文字列になります。右辺は省略可能で、省略時は左辺と同じ文字列が終端文字列になります。
列挙は、Javaのenum型としてモデル化されるので、とても扱いやすいですし、DSLエディタ上でもコンテンツアシストされて、とても便利です。


データタイプ(一般的な終端ルール)

QualifiedName returns ecore::EString :
  ID ('.' ID)*
;
構文ルールが展開されると、最終的には終端ルールが明確になる必要があります。
これまで見てきた、列挙やキーワードオプション、クロスリファレンスのような特別な終端ルールもありますが、通常は、識別子、文字列リテラル、数値リテラルなどの、一般的な終端ルールが必要になります。

Xtextでの終端ルールは、テキストパターンとモデル型を定義します。
上記の例では、1行目の「QualifiedName」は終端ルール名で、「returns」句の右の「ecore::EString」は、この終端ルール適用時に返されるモデル型を示します。「returns」句を省略すると、モデル型は文字列型になります。
2行目の「ID('.' ID)*」は、この終端のテキストパターンを示しています。
ID終端ルールは、グラマー宣言で引き込んでいる既定のCommonTerminalsから再利用していますが、内容は一般的な識別子の正規表現パターン(先頭英字で残りは英数字)になっています。
この他にも、CommonTerminalsには、INTやStringなどのよく利用する終端ルールが定義されているので、簡単なDSLを作る際にはそのまま利用することができます。

Xtextの終端ルールが、任意のモデル型を指定できるのは、とても大きな特徴です。
これは、自由なモデル型のリテラル(相当)を作れることを意味しています。
例えば、「2011-01-23」などを日付リテラルとして扱ったり、特別な制約がある数値的リテラルを作ったりもできます。
独自のモデル型の終端や、独自の制約を持つ終端を定義するには、文字パターンの定義だけではなく、モデル上で使用する実際のJava型の存在と、文字パターンからそのJava型に変換するValueConverterの実装が必要です。
これについては、また別途まとめようと思います。


0 件のコメント:

コメントを投稿