ジェネレーターユーザガイド Demo1
Generator ユーザーガイドのデモ 1
このデモでは、入力 XML ドキュメントごとに java アプリケーションを生成するジェネレーターを作成します。
以前に作成したソリューション「test_models 」で「generator_demo.test1 」モデルを再利用します。このモデルは「jetbrains.mps.sampleXML 」言語を使用し、「ボタン」と「ラベル」の 2 つの XML ドキュメントを含みます。
出力 java アプリケーションを生成するために、これらの各ドキュメントにルートマッピングルールを適用します。アプリケーションのメインメソッドでは、生成されたコードがスイングフレームをインスタンス化し、要求されたスイングコンポーネントをコンテンツペインに追加します。コンポーネントは、入力ドキュメントのルート要素の名前に応じて、JButton または JLabel のいずれかになります。
「ボタン」XML ドキュメントは、フレーム内にボタンを表示する Java アプリケーションに変換されます。
新しい言語
最初に行うことは、新しいジェネレーターで simpleXML を拡張する言語を作成することです。XML を生成する代わりに、Java コードを生成する必要があります。
プロジェクトのポップアップメニューで「新規」->「言語」を選択します
言語名を入力してください: 'generator_demo.demoLang1'
'jetbrains.mps.sampleXML' および 'jetbrains.mps.baseLanguage' 言語を拡張言語として demoLang1 言語プロパティの依存関係セクションに追加しますダイアログ
新しいジェネレーター
MPS は、「generator_demo.demoLang1 」言語内に空のジェネレーターモジュールと、空のマッピング構成ノード「main」を含むジェネレーターモデル「main @generator」を作成しました。そうでない場合は、「generator_demo.demoLang1 」言語のコンテキストメニューから簡単に作成できます。
マッピング構成は、すべてのジェネレータールールが宣言され、そこからテンプレートを参照できるジェネレーターの「エントリポイント」として機能します。テンプレートには、入力モデルから入力する値の宣言されたプレースホルダーを持つターゲットコードのスニペットが含まれます。テンプレートは、MPS モデルからモデルへの変換プロセスの中核です。
モデルステレオタイプ 'generator'(モデル名の記号 '@' の後に表示)により、MPS は通常のモデルからジェネレーターモデルを識別できます。ジェネレーターモデルのノードは、そのノードがジェネレーター言語自体の一部でない限り、テンプレートとして解釈されます。
たとえば、マッピング構成ノードはジェネレーター言語の一部です(「MappingConfiguration」の概念は言語「jetbrains.mps.lang.generator」で宣言されています)。
次のステップで作成するクラスノードは、ジェネレーター言語の一部ではないため、ジェネレーターのテンプレートとして使用されます。
ルートマッピングルール
入力 XML ドキュメントごとに Java アプリケーションクラスを生成する最初のルールを作成しましょう。
エディターで「main」という名前のマッピング構成を開きます
ルートマッピングルールセクションに新しいルールを追加する (セクションでキャレットを使用して Insert または Enter を押します)
ルールの適用可能なコンセプトを選択します: '資料'
入力ドキュメントごとにクラスを生成するため、マッピングルールの一部として指定する必要があるこのルールのテンプレートは、クラス、つまり BaseLanguage で定義された「ClassConcept 」コンセプトのインスタンスになります。
そのテンプレートを作成する最も簡単な方法は、インテンションを適用することです(エディターの左端を参照してください? ):
キャレットが赤いフィールド「<テンプレートなし>」内にあるときに Alt-Enter を押します。
新しいルートテンプレートを選択します
クラスを選択します。
エディターで新しく作成されたクラスを開きます (参照で Ctrl + 左クリックまたは Ctrl + B を使用します)
プロパティマクロ
テンプレートは、入力モデルからの値でパラメーター化する必要があります。MPS は、入力モデルからテンプレートに値をフックするためのいくつかのタイプのマクロを提供します。開始するプロパティマクロは、生成時に出力モデルノードのプロパティの値を計算するために使用されます。
非常に些細なことから始めましょう。入力ドキュメントの名前と同じ名前の出力クラスを生成したいと思います。
出力クラスの名前のプロパティマクロを作成します。
クラス名の内側のどこかにキャレットを置きます
Ctrl-Shift + M を押して、メニューでプロパティマクロを選択します
または、Alt+Enter コマンドを使用してインテンションを使用することもできます。
エディターでマクロノードを選択し(「$」記号として表示)、そのインスペクターウィンドウを開きます。(Alt-Shift + I)
クラスの生成時にクラスの実際の名前を計算する値関数のコードを入力します
関数は、ノードパラメーターを介して元のドキュメントノードを参照できます
この値関数は、この場合、元のドキュメントの名前を返します
main() メソッド
生成されたコードで Java Swing コンポーネントを使用する予定なので、java.awt および javax.swing パッケージの MPS java_stub モデルをジェネレーターモデルにインポートする必要があります。
Ctrl-M を押します (インポートモデル)
「java.awt@java_stub」モデルを選択します
Ctrl-M をもう一度押します
「javax.swing@java_stub」モデルを選択します
インポートが邪魔にならないため、main() メソッドを作成できます。'psvm' と入力すると、空の main メソッドを挿入する自動アクションがトリガーされます。または、メソッドシグネチャーを自分で入力することもできます。
「String []」を入力しようとしてつまずいた場合 - パニックに陥らないでください。一人ではありません。ヘルプはこちら
スイッチマクロ
入力 XML ドキュメントの実際の値に応じて、新しいボタンまたはラベルを渡す必要があるのに、なぜ container.add() メソッドに null を渡すのか疑問に思ったかもしれません。これが、このテンプレートで行う必要がある最後の作業です。つまり、「container.add(null)」式の「null」引数を、Swing コンポーネントを作成する式に置き換えます。
入力ドキュメントのルート要素の名前が「button」の場合は「newJButton()」式を生成し、ルート要素の名前が「label」の場合は「newJLabel()」を生成します。
この置換を実行するために、「null」引数をスイッチマクロに「ラップ」します。
SWITCH マクロは、「ラップされた」テンプレートノードを新しいノードに置き換えます。置換ノードは、関連するテンプレートスイッチでどのケース条件が満たされるかに応じて作成されます。
まず、「switch_JComponentByElementName」という名前の新しいテンプレートスイッチを作成しましょう。
条件コードの入力を開始するには、Insert を押します
次のスクリーンショットの「<T ... T>」はインラインテンプレートと呼ばれます。スクリーンショットの注も参照してください。
以上です。要素の名前をテストしています。「ボタン」の場合、「new JButton()」を生成します。同じように、それが「ラベル」の場合、「new JLabel()」を生成します。「ボタン」でも「ラベル」でもない場合、エラーが発生しています。
これで、'container.add(null)' 式の SWITCH マクロを 'null' 引数ノードにアタッチする準備ができました。
「ドキュメント」テンプレートの「main()」メソッドに戻る
「container.add(null)」式で「null」ノードを選択します
Ctrl-Shift-M を押して、抽象ノードマクロを追加します
Ctrl + Space を押して完了メニューを呼び出し、$SWITCH$ を選択します
$SWITCH$ マクロのインスペクターに移動
マップされたノード関数にコード(以下を参照)を入力し(挿入を押して入力を開始)、スイッチに関する決定を行うノードを設定します
切り替えプロセスを参照するために以前に作成した「switch_JComponentByElementName」テンプレートスイッチノードを参照します
マップされたノード関数は何をし、なぜ必要なのですか?
ここまで、map_Document テンプレート内の入力ノードは Document でした。しかし、テンプレートスイッチ「switch_JComponentByElementName 」は、Document ではなく Element を入力として想定しています。入力ノード (Document ) を新しい入力ノード (Element) に置き換える必要があります。式「node.rootElement 」は、現在の入力ドキュメントのルート要素を返します。ルート要素は、テンプレートスイッチ内で適用可能な新しい入力ノードになります。
最初のテストの準備をする
ジェネレーターモデルに加えた変更は、ジェネレーターが作成された後にのみ他のモジュールに表示されることを覚えておくことが非常に重要です。変更を加えた後の最後のアクションは常に同じである必要があります: ジェネレーターを作る。
ジェネレーターにはモデルが 1 つしかないため、テンプレートの編集が終了したら、Shift + Control + F9 または Shift + Cmd + F9(モデルの作成)を押します。
テストモデルの生成
「test_models」ソリューションの「test1」モデルに戻りましょう。ソリューションには複数の XML ドキュメントが含まれており、demoLang1 で XML ノードのセマンティクスを定義しました。あいにく、MPS は、最初に言わずにこれらの 2 つの部分を結合することはできません。MPS は、モデル「test1」が「test1」のどこでも明示的に demoLang1 を使用していないため、sampleXML と demoLang1 の 2 つの言語で記述されていることを理解していません。
demoLang1 は独自の概念を定義しないため、demoLang1 モデル「test1」を実際に使用することはできないため、MPS に明示的に demoLang1 ジェネレーターをモデル「test1」の生成プロセスに含めるよう指示します。
モデル 'test1' のプロパティを開く
言語 'generator_demo.L1' を世代が関与する言語セクションに追加します
'test1' モデルのポップアップメニューで生成されたファイルのプレビューコマンドを実行します。MPS は 2 つの java ファイルを生成し、エディターに表示します。
MPS は、「test1」モデルの作成または再構築の一部として、生成された Java ソースを Java バイトコードにコンパイルすることもできます。生成されたソースの Java コンパイルを有効にするには、JDK への依存関係を「test_models」ソリューションに追加する必要があります。
関連ページ:
よくある質問 (FAQ)
ドメイン固有言語、プロジェクショナルエディターおよび MPS:ここでは、MPS に関して最もよくある質問に対する答えを見つけることができます。ドメイン固有言語(DSL)とは何ですか? それらは「実際の」プログラミング言語とどう違うのですか? DSL は、特定の問題領域向けに最適化された言語です。通常、Java、C、Ruby などの汎用言語ほど複雑ではありません。DSL は通常、DSL が設計されているドメインまたはフィールドの専門家と緊密に連携して開発されます。多くの場合、DSL は、DSL が対...
ジェネレーターデモ
ジェネレーターチュートリアル:MPS で言語ジェネレーターを定義および拡張するプロセスをガイドする、更新されたジェネレーターチュートリアルへようこそ。チュートリアルは 7 つのパートで構成されており、徐々に複雑さが増しています。すべてのデモは、同じ基本的なストーリー、つまり Java Swing コンポーネントへの XML コードの変換を共有しています。各デモは前のデモに基づいており、より高度な(または場合によっては単に異なる)機能、プラクティス、アプローチを示しています。すべてのデモは論理的に...
ジェネレーターユーザガイド Demo2
Generator ユーザーガイドデモ 2:このデモでは、Java Swing アプリケーションを再度生成しますが、前のデモ 1 とは異なり、今回は入力モデルごとに 1 つの Java アプリケーションになります(デモ 1 では、入力 XML ドキュメントごとに個別の Java アプリケーションを生成しました)。デモ 2 が作成する単一の Java アプリケーションには、入力モデルのすべての XML ドキュメントに記載されているすべてのコンポーネントが含まれます。新しい言語:最初に少し技術的な...