2

次の機能を備えた、xtext を使用した信じられないほど単純な DSL を作成したいと考えています。

  • Number と String の 2 つのプリミティブ型があります。
  • ユーザーは、フィールド宣言で構成される独自のクラスを定義できます
  • フィールド宣言は名前を型に関連付けます。型はクラスまたはプリミティブにすることができます

以下は、DSL での私の試みです。クラス定義と参照は正常に機能しますが、プリミティブ型を使用する方法がわかりません。'String' および 'Number' リテラルが機能していません:

Model:
    (classes+=Class)*
    (fields+=Field)*;

FieldType: Class | 'String' | 'Number';

Field:
    type=[FieldType] name=ID ";";

Class:
    "class" name=ID
    "{"
        (fields+=Field)*
    "}";

上記の DSL に対して有効であると思われる例を次に示します。

Class SomeClass {

}

// This works!
SomeClass reference;

// This does not, doesn't recognise the "String" literal
String string;

今後は割り当てをサポートすることに注意してください。したがって、私の DSL は、数値/文字列リテラルの概念を組み込む必要があります。Number someNumber = 123;

4

1 に答える 1

1

寝たきりなので、アプローチを変えるのが正解だと思います。上記の定義では、

Field:
    type=[FieldType] name=ID ";";

これは、2 つの部分で構成される「フィールド」と呼ばれるルールを定義します。「型」と「名前」。問題を提示しているのはタイプ部分です。角括弧は、 のインスタンスが期待されていることを示しますFieldType。これは次のとおりです。

FieldType: Class | 'String' | 'Number';

これで、クラスのインスタンスを持つことができることは明らかですが、意味的には「文字列」または「数値」リテラルのインスタンスを持つ方法はありません。

これが、上記の DSL でプリミティブを宣言させない理由だと思います。文字列/数値の「型」は、インスタンスを持つことができる要素ではありません。


さらに考えてみると、プリミティブなフィールドの定義とクラスのインスタンスであるフィールドの定義の間には、非常に重要な違いがいくつかあります。たとえば、クラスのインスタンスでのみメソッドを呼び出すことができます (私の場合、String を真のプリミティブとして扱っているため、メソッドはありません)。

PrimitiveFieldしたがって、1 つは forと 1 つはfor という 2 つの異なるタイプの宣言を持つことがおそらく重要ですObjectField。フィールドは次のいずれかになります。

Model:
    (classes+=Class)*
    (fields+=Field)*;

PrimitiveType: 'String' | 'Number' | 'Boolean';

Field:
    PrimitiveField | ObjectField
;

PrimitiveField:
    type=PrimitiveType name=ID ";"
;
ObjectField:
    type=[Class] name=ID ";";

Class:
    "class" name=ID
    "{"
    (fields+=Field)*
    (methods+=Method)*
    "}";
于 2013-10-19T11:21:15.933 に答える