エディター
言語の構造が定義されたら、開発者がそれを使用して AST を簡単に構築できるようにする手段を作成することになるでしょう。AST を直接操作することは、あまり直感的でも生産的でもないでしょう。AST を非表示にして、ユーザーに快適で直感的な操作を提供するのが、言語エディターのロールです。
エディターの概要
ノードのエディターは、そのビューおよびそのコントローラーとして機能します。エディターにノードが表示され、ユーザーはそれを変更、置換、削除などできます。異なる概念のノードは異なるエディターを持ちます。言語デザイナーは、自分の言語のすべての概念に対してエディターを作成する必要があります。
MPS では、エディターはセルで構成されています。セルには、他のセル、テキスト、UI コンポーネントが含まれています。各エディターには、それが指定されている概念があります。1 つの概念には、複数のエディター宣言を含めることはできません(または、まったく宣言できません)。概念にエディター宣言がない場合、そのインスタンスは、エディター宣言がある概念の最も近い先祖のエディターで編集されます。
特定の概念のエディター(つまり、この概念のノードのエディターに表示する必要のあるセル)を記述するために、言語設計者は、単にエディター言語と呼ばれる専用言語を使用します。ご覧のとおり、MPS は言語指向プログラミングの原則をそれ自体に適用しています。
エディターの説明は、それが保持しているセルの説明で構成されています。このような記述を「セルモデル」と呼びます。たとえば、エディターが変更不可能なテキストを含む一意のセルで構成する場合は、エディターの説明で定数セルモデルを作成し、そのテキストを指定します。エディターを複数のセルで構成する場合は、コレクションセルモデルを作成し、その中にその要素のセルモデルを指定します。
コンセプトエディターの定義
概念のエディターの定義には、次の 2 つのセクションが含まれます。
ノードセルレイアウト - コンセプトの実際の(メイン)エディター定義を保持します
インスペクションされたセルレイアウト - ユーザーがメインウィンドウのこのノードのエディターにカーソルを置いたときにインスペクターツールウィンドウに表示される二次定義を保持します。通常、エディターのインスペクター部分は、概念の重要度の低いプロパティや、読み取り / 変更の頻度が低いプロパティを提供するために使用されます。
問題が発生した場合のリフレクティブエディターへのフォールバック
実行時の例外によりエディター定義の初期化に失敗すると、対応するセルにデフォルトのリフレクティブエディターが表示されます。メッセージツールウィンドウに説明的なエラーが表示され、ユーザーは完全なスタックトレースを取得したり、問題のセルに移動したりできます。

既存のテキストを上書き
既存のテキストを上書きすると、テキストエディターと射影エディターの区別がさらに曖昧になります。テキストセルに入力するときに、入力した文字がすでにキャレットの位置に存在している場合、画面上の既存の文字を上書きしたかのようにキャレットが右に移動します。この機能は、キーストロークが適切に処理されず、それ以外の場合は無視される (定数セルなど) か、セルの内容が無効になる場合にのみトリガーされます。この機能はデフォルトでオンになっており、設定 / エディター /MPS エディタータブでオフにできます。
選択変更時にモデルと同期する
ユーザーが制約 (プロパティ値または参照) に違反する値をセルに挿入すると、そのセルは赤になります。エディターにはエラーのある値 (赤色) が表示されていますが、モデルには以前の有効な値がまだ含まれています。構成可能なオプションを使用すると、エラーのあるセルからカーソルまたはフォーカスを移動した後、エディターで元の有効な値を復元するかどうかを指定できます。この機能はデフォルトではオフになっており、設定 / エディター /MPS エディタータブでオンにできます。
セルモデルの種類
定数セル | このモデルは、常に同じテキストを含むセルを表します。定数セルは通常、テキストベースのプログラミング言語の「キーワード」を反映します。 |
---|---|
収集セル | 他のセルを含むセル。水平に配置できる (コレクション内のセルは一列に並べられる)、垂直 ![]() (セルが重なり合っている)またはいわゆる「インデントレイアウト」になっている (セルは水平に配置されますが、行が長すぎる場合はテキストのように次の行に折り返され、次の各行の前にインデントが付けられます)。 インスペクターでは、結果のセルコレクションで折りたたみを使用するかどうか、および中括弧を使用するかどうかを指定できます。折りたたむと、セルリストを 1 つのセルに縮小(折りたたむ)し、必要に応じてそこから拡張(展開)することができます。大きなルートを編集するときにあなたの言語で書くプログラマーにとっては便利です。彼 / 彼女はいくつかのセルを折りたたんで、現在のタスクに必要のないすべての情報を隠すことができます。たとえば、大きなクラスを編集する場合、現在編集しているメソッドを除くすべてのメソッド本体を折りたたむことができます。 true に設定すると、デフォルトの折りたたみプロパティにより、ユーザーが手動で展開しない限り、コレクションが初めて表示されたときに折りたたまれた状態で表示されます。 コレクションセルでは、ユーザーに直感的な視覚的なアクションを提供するコンテキストアシスタントを指定することもできます。詳細については、「コンテキストアシスタントのドキュメント」を参照してください。 |
プロパティセル | このセルモデルは、ノードの特定のプロパティの値を表示するセルを表します。プロパティの値はプロパティセルで編集できるため、プロパティセルはビューとしてだけでなく、コントローラーとしても機能します。インスペクターでは、プロパティセルを読み取り専用にするか、プロパティ値を編集できるようにするかを指定できます。 |
子セル | このセルモデルには、ノードの概念内の特定のリンク宣言への参照が含まれます。結果のセルには、リンクのターゲット (ほとんどの場合、参照先ではなく子) のエディターが含まれます。たとえば、2 つの子 (「leftOperand」と「rightOperand」) を持つバイナリ演算 (「+」) がある場合、演算のエディターモデルは次のようになります。左オペランドの参照ノードセル、「+」の定数セル、右オペランドの参照ノードセルを含むインデントコレクションセルです。右オペランドのエディター、次に「+」のセル、左オペランドのエディターの順にレンダリングされ、1 行に配置されます。これまで見てきたように、また名前からもわかるように、このタイプのセルモデルは通常、子のエディターを表示するために使用されます。 |
参照先セル | 主に参照ターゲットを表示するために使用されます。参照セルと子セルの主な違いは、参照ターゲットのエディター全体を表示する必要がない、または表示したくないということです。例: 特定のノード、たとえばクラスタイプが java クラスへの参照を持っている場合、そのクラスのエディター全体をそのメソッドやフィールドなどとともに表示したくありません。その名前を表示したいだけです。子セルをそのような目的に使用することはできません。参照セルを使用する必要があります。 参照セルを使用すると、ターゲット自体のエディターを使用する代わりに、参照ターゲットに対して別のインラインエディターを表示できます。ほとんどの場合、これは非常に単純です。参照ターゲットのセルは通常、ターゲットの名前を持つプロパティセルのみで構成されます。 |
子リストセル | このセルは、同じロールのノードの子の複数の子セルを含むコレクションです。たとえば、メソッド呼び出しのエディターには、実際の引数をレンダリングするための子リストセルが含まれます。子リストは、インデント(テキストのような)、水平または垂直にすることができます。 このセルモデルから生成されたセルは、指定されたロールの子の挿入と削除をサポートするため、ビューとコントローラーの両方として機能します。挿入のデフォルトキーは Insert と Enter(それぞれ、選択した子の前または後に子を挿入するため)であり、削除のデフォルトキーは Delete です。 リストの区切り文字を指定することもできます。区切り文字は、子のセル間の定数セルに表示される文字です。セルリスト内でこの文字のキーを押すと、選択した子の後に新しい子が挿入されます。たとえば、メソッド呼び出しの実際のパラメーターを表すリストの区切り文字はコンマです。セパレーターを定義するクエリは、コレクション内のノードの位置に反応する可能性があるため、単一の子コレクション内のセパレーターは、異なる位置で異なる可能性があります。 インスペクターでは、結果のセルリストで折りたたみを使用するかどうか、および中括弧を使用するかどうかを指定できます。折りたたむと、セルリストを 1 つのセルに縮小(折りたたむ)し、必要に応じてそこから拡張(展開)することができます。大きなルートを編集するときにあなたの言語で書くプログラマーにとっては便利です。彼 / 彼女はいくつかのセルを折りたたんで、現在のタスクに現在のタスクに必要ではないすべての情報をエディターで隠すことができます。たとえば、大きなクラスを編集する場合、現在編集しているメソッドを除くすべてのメソッド本体を折りたたむことができます。 |
インデントセル | |
UI コンポーネントセル | このセルモデルを使用すると、言語設計者はノードのエディター内に任意の UI コンポーネントを挿入できます。言語設計者は、JComponent を返す関数を作成する必要があり、そのコンポーネントは生成されたセルに挿入されます。このようなコンポーネントは、エディターが再構築されるたびに再作成されるため、コンポーネント内の状態を維持しようとしないでください。すべての状態は、ビュー(コンポーネント)ではなく、モデル(つまり、ノード、そのプロパティ、参照)から取得してモデルに書き込む必要があります。 このようなセルモデルの適切な使用例は、プロパティ内のファイルへのパスを保持し、コンポーネントがモーダルファイルチューザーをアクティブにするボタンである場合です。ファイルチューザーでデフォルトで選択されたパスが上記のプロパティから読み取られ、ユーザーが選択したファイルパスがそのプロパティに書き込まれます。 |
モデルアクセス | モデルアクセスセルのモデルは、プロパティセルを一般化したものであるため、より柔軟性があります。プロパティセルが単にプロパティの値を示し、ユーザがその値を変更できるのに対し、モデルアクセスセルはノードの状態に基づいて任意のテキストを示し、ユーザがセルのテキストに加えた変更に基づいてノードを任意に変更することができます。 プロパティセルを機能させるには、そのセルを介してアクセスするプロパティを指定するだけで済みますが、モデルアクセスセルを機能させるには、言語設計者が「get」、「set」、「validate」の 3 つのメソッドを記述する必要があります。最後の 2 つは、ある程度オプションです。 「get」メソッドはノードを受け取り、セルのテキストとして表示される文字列を返します。「set」メソッドは文字列 (セルのテキスト) を受け取り、必要に応じてこの文字列に従ってノードを変更します。「validate」メソッドはセルのテキストを受け取り、それが有効かどうかを返します。ユーザーによる変更後にセル内のテキストが無効になった場合、そのテキストは赤でマークされ、「set」メソッドには渡されません。 「検証」メソッドが指定されていない場合、セルは常に有効になります。「設定」メソッドが指定されていない場合、セルのテキストの変更はノード自体には影響しません。 |
次に該当するエディター | より具体的なエディターは、新しい次に適用可能な編集者エディターセルを通して、同じ概念のあまり具体的でないエディターを再利用することができます。次に適用可能なエディターセルはプレースホルダとして使用されます。プレースホルダは、特定性の低いエディターを見つけるためのロジックを再適用し、見つかったエディターをその場所に挿入します。例: 特定のコンテキストヒントに特化したエディターは、次に適用可能なエディターセルの周囲に視覚的な儀式を提供するかもしれません。次に適用可能なエディターセルのコンテキストヒントを削除することで、MPS はエディター検出ロジックを再評価し、見つかったエディターを次の適用可能なエディターセルに提供します。 ![]() 特にこのメカニズムは、一般的なコメントアウト機能をカスタマイズするときに「コメントアウト」されたノード用のエディターを実装するために頻繁に使用されています。 |
ツールチップ | ユーザーがエディターの一部にマウスを移動したときに、小さなツールチップポップアップウィンドウに役に立つメッセージを表示できます。ツールチップ言語はエディターモデルにインポートする必要があります。ユーザーは、すべてのセルをツールチップで視覚化する「ツールチップレーダー」を利用できます。コントロールキーを押したままマウスを動かすだけです。この言語は、mbeddr プロジェクトから MPS に採用されました。 ![]() |
イメージセル | エディターにイメージを含めることができます。イメージファイルは直接選択することも、絶対パス文字列またはモジュールのルートからの相対パスで指定することもできます。 |
カスタムセル | 言語設計者が希望するエディターを作成するために他のセルモデルが不十分な場合は、もう 1 つのオプションが残されています。任意のカスタムセルを返すセルプロバイダーを作成するというものです。唯一の制限は、「EditorCell」インターフェースを実装する必要があることです。 |
エディターコンポーネントとエディターコンポーネントセル
異なる概念のための 2 つ以上のエディター宣言が共通部分を持ち、それがそれらのエディターのそれぞれに重複していることがあります。冗長性を避けるために、エディターコンポーネントと呼ばれるメカニズムがあります。コンセプトエディターの宣言と同じように、エディターコンポーネントを作成するためのコンセプトを指定してセルモデルを作成します。書かれると、そのコンポーネントは指定された概念の子孫のためのエディター宣言で使用される可能性があります。エディター宣言内でエディターコンポーネントを使用するには、特定のセルモデルを作成します。エディターコンポーネントセルモデル、およびエディターコンポーネント宣言をこのセルモデルの参照のターゲットとして設定します。
セルレイアウト
各コレクションセルには、子ノードの配置方法を説明する「セルレイアウト」プロパティがあります。レイアウトにはいくつかあります。
インデントレイアウト - テキストのようにセルを配置します。
水平レイアウト - セルを水平に並べて配置します。
垂直レイアウト - セルを垂直に配置します。
上付き / 下付きレイアウト – セルの上付きまたは下付きを w.r.t に配置します。ベースライン。
フローレイアウト - セル間にギャップがないようにセルを水平に並べて配置します。右マージンを超えるセルは次の行に配置されます。
テーブルレイアウト - セルを表形式に配置します。
垂直グリッドレイアウト - セルを垂直に配置し、ネストされた水平レイアウトが連携してセルをグリッドに配置できるようにします。
インデントレイアウトセルには、レイアウトをカスタマイズするためのプロパティがいくつかあります。レイアウトセル自体に適用できるものと、レイアウトセル内のセルに適用できるものがあります。
indent-layout-indent- このセルは、行の最初に表示された場合、インデントが先頭に追加されます
indent-layout-new-line - このセルは行の最後になります
新しい行のインデントレイアウト - このセルは次の行の先頭になります
indent-layout-new-line-children - このコレクションセルのすべての子セルは別々の行に表示されます
indent-layout-wrap-anchor - このコレクションセルの子セルが画面の幅を超えると、それらはこのコレクションと垂直方向に揃うように折り返されます。
indent-layout-indent-anchor - 後続のすべてのインデントは、現在のコレクションセルのインデントを基準にして計算されます。
indent-layout-no-wrap - セルは、新しい行で最初に終わるようにラップすることはできません。
上付き / 下付きレイアウトセルを使用すると、内部セルをベースラインよりわずかに上 / 下に設定できます。内側のセルのスタイルをトリガーするには、対応する script-kind スタイルを子セルに追加します。例:

フローレイアウトセルはセル間にギャップを提供しないため、個々のセルで paddiing-left/right プロパティを使用することを検討してください。
テーブルレイアウト内で、table-component プロパティを使用して、ネストされたセルをテーブルの垂直(列)コレクションとして処理するか、水平(行)コレクションとして処理するかを指定します。
スタイル
エディターセルをスタイリングすると、言語設計者はコードの読みやすさを向上させるための非常に強力な方法を手に入れることができます。キーワード、定数、呼び出し、定義、式、コメント、その他の言語要素をそれぞれ異なる色またはフォントで表示することで、開発者はより簡単に構文を理解することができます。開発者が編集できないように、スタイリングを使用してエディターの領域を読み取り専用としてマスクすることもできます。
各セルモデルには、セルの表示を決定するいくつかの外観設定があります。たとえば、フォントの色、フォントのスタイル、セルを選択できるかどうかなどです。これらの設定は、スタイルシートと呼ばれるエンティティに結合されます。スタイルシート は、インラインにすることも、特定のセルモデルと一緒に記述することも、個別に宣言して多くのセルモデルで使用することもできます。インスペクタービューの各セルには、インラインスタイルシートとスタイル参照の両方が指定されています。


設定は単一の値で指定する必要はありません。すべての設定に対してクエリオプションも利用できます。その場合、開発者がコンセプト関数を実装する必要があります。これにより、目的の値が返されます。

さまざまな目的のためにいくつかのスタイルシートを宣言することをお勧めします。もう 1 つの良い習慣は、言語のエディターを開発するとき、および言語の拡張機能を開発するときに、スタイルガイドラインを念頭に置くことです。例: BaseLanguage には、キーワード(Java のキーワードに対応する BaseLanguage エディターの定数セルに適用される)、静的フィールド(静的フィールド宣言および静的フィールド参照に適用される)、インスタンスフィールド、数値リテラル、文字列リテラルなどのスタイルがあります。BaseLanguage の拡張機能を開発するときは、キーワードスタイルを新しいキーワードに適用したり、フィールドスタイルを新しいタイプのフィールドに適用したりする必要があります。
スタイルシートは CSS スタイルシートとよく似ています。これはスタイルクラスのリストで構成され、その中にいくつかのスタイルプロパティの値が指定されています。MPS はさらに、スタイルを拡張し、プロパティ値を上書きするためのメカニズムを提供します。
スタイルのプロパティ
ブールスタイルプロパティ
selectable- セルを選択できるかどうか。デフォルトでは True。
読み取り専用 - セルとネストされたセルを変更できるかどうか。デフォルトでは False。セルツリーの断片を凍結するために設計されています。
編集可能 - セル内のテキストを変更できるかどうか。デフォルトでは、定数セルモデルの場合は false、他のセルモデルの場合は true です。
draw-border- セルの周囲に境界線を描画するかどうか
ドローブラケット - 括弧がセルの周囲に描画されるかどうか
first-position-allowed / last-position-allowed- テキストを含むセルの場合、キャレットが最初 / 最後の位置にあることを許可するかどうかを指定します (つまり、セルのテキスト全体の前後)
補完メニューからプロパティ値を選択するか、クエリ、つまりブール値を返す関数を指定できます。

パディングプロパティ
padding-left/right/top/bottom- 浮動小数点数。テキストセルのパディング、つまりセルのテキストとセルの左側と右側の間にそれぞれどのくらいのスペースがあるかを指定します。
句読点のプロパティ
コレクション内のすべてのセルは、デフォルトでは 1 つのスペースで区切られています。時々私達は一緒に置かれるセルを必要とします。
句読点 - 左 - このプロパティが true の場合、セルの左側からのスペースが削除され、セルの最初の位置が許可されなくなります。
句読点 - 右 - このプロパティが true の場合、セルの右側からのスペースが削除され、セルの最後の位置が許可されなくなります。
水平ギャップ - コレクション内のセル間のギャップサイズを指定します。デフォルト値は 1 スペースです。
たとえばコード
「(」と「1」の間、および「1」と「)」の間にスペースは必要ありません。プロパティの句読点(セル「(」の右側)とプロパティの句読点(セル「)」の左側を追加する必要があります。
カラースタイルプロパティ
テキストの前景色 - セルテキストの色 (テキストセルのみに影響する)
テキストの背景色 - セルテキストの背景色 (テキストセルのみに影響します)
背景色 - セルの背景色。すべてのセルに影響します。テキストセルにゼロ以外のパディングとテキストの背景色がある場合、セルの背景色は余白の色になります。完了メニューから色を選択するか、クエリ、つまり色を返す関数を指定することができます。
インデントレイアウトプロパティ
indent-layout-indent- すべての行がインデント付きで配置されます。このプロパティは、コードブロックのインデントに使用できます。
indent-layout-new-line- このセルの後に新しいラインマーカーがあります。
indent-layout-on-new-line- このセルは新しい行に配置されます
indent-layout-new-line-children- コレクションのすべての子が新しい行に配置されます
indent-layout-no-wrap- このセルの前に行が折り返されることはありません
その他のスタイルプロパティ
フォントファミリ
フォントサイズ
フォントスタイル - プレーン、太字、斜体、太字斜体のいずれかになります。
レイアウトの制約 -
フローレイアウト用
なし - デフォルトの動作
句読点 - フローレイアウトの前の項目は常に、この制約が割り当てられている項目と同じ行に配置する必要があることを意味します。
noflow - フローレイアウトからセルを除外します。現在の行は終了し、アイテムはその下に配置されます。この項目の後に新しい行が開始され、通常のフローレイアウトが適用されます。このスタイルは写真をテキストの中に埋め込むのに使うことができます。
下線付き - 下線付き、下線なし、そのままのいずれかになります(「現状のまま」とは、囲んでいるセルコレクションのプロパティに依存することを意味します)。
スタイルプロパティの伝播
一部のスタイルプロパティは、それらが適用されるセルにのみ影響しますが、他のプロパティの値は、セルサブツリー(ネストされたセル)にプッシュされ、子セルの一部がプロパティに独自の値を指定するまで適用されます。セル階層にプッシュされるこのような継承可能なプロパティには、text-foreground-color、text-background-color、background-color、font-style、font-size などがあります。
ユーザー設定のスタイル ...
言語設計者はスタイルシートで独自のスタイル属性を定義してからエディターで使用できます。これにより、言語エディターの定義の柔軟性が高まります。属性は異なるタイプの値を保持することができ、オプションでデフォルト値を提供できます。

カスタムスタイル属性には 2 種類あります。
単純な - 単一のエディターセルにのみ適用されます
継承 - セルとそのすべての子孫セルに再帰的に適用される
エディター定義で style 属性を使用するには、言語が属性を定義する言語をインポートする必要があり、エディターアスペクトは使用される言語の中で定義言語をリストする必要があります。BaseLanguage コード内からカスタム属性を参照するには、次の StyleAttributeReferenceExpression コンセプトへのアクセスを得るために jetbrains.mps.lang.editor をインポートする必要があります。
スタイル継承
本当に使用できるようにするには、特定のスタイルクラスが明示的にオーバーライドされないすべてのスタイルプロパティの値を継承することを説明するために、スタイルクラスに拡張メカニズムが必要です。特別なスタイルプロパティ apply を使用して、親スタイルクラスで指定されたすべてのプロパティの値をスタイルクラスにコピーできます。apply プロパティを使用することは、親スタイルクラスからすべてのプロパティをコピーして貼り付けることと意味的に同等です。条件付きでスタイルプロパティ値を適用するために、apply-if バリアントも使用できます。従来のスタイル拡張とは異なり、適用メカニズムでは複数のクラスを継承できます。
unapply プロパティを使用すると、スタイルクラスは、選択した継承プロパティの効果を停止できます。例: コメントアウトされたコードのスタイルクラスは、コード要素がすべて灰色に見えるようにするスタイルをプッシュダウンます。ただし、ユーザーがリンクを見つけてクリックできるように、リンクを通常の色でレンダリングする必要がある場合があります。
親スタイルで指定されたプロパティと継承セルで明示的に定義されたプロパティ間の潜在的な競合は、順序に基づいて解決されます。最後に指定した値は、同じスタイルプロパティの以前のすべての値をオーバーライドします。
例: ConsoleRoot の概念は、編集が許可される単一のポイント(commandHolder セル)のみを備えた読み取り専用エディターを提供します。まず、readOnly スタイルクラスがエディターで設定されます。

次に、readOnly スタイルクラスが commandHolder セルに適用されません。

readOnly スタイルクラスは次のように定義されています。

スタイルの優先順位
スタイルクラスは、他のスタイルクラスまたは複数のクラスよりも優先されるように宣言できます。
スタイルクラスが何よりも優位ではない場合、低レベルスタイルクラスです。
スタイルクラスを支配するように宣言しますが、オーバー支配するスタイルクラスを指定しない場合は、すべての低レベルのスタイルクラス上支配し、スタイルクラスが考慮される(何のスタイルクラスを指定しますが、本を支配する言葉ではありません)。
支配関係は推移的であり、サイクルは許可されていません。
支配関係は、継承可能な属性を持つスタイルに対してのみ意味があります。あるスタイルプロパティの一方の値が親からプッシュダウンされ、現在のセルに適用されているスタイルクラスに同じプロパティの別の値が指定されている場合、結果として生じる動作は 2 つのスタイルクラス間の関係によって異なります。
両方のスタイルクラスが low-level の場合、parent からプッシュされた値は無視され、現在のセルのスタイルクラスからの値に置き換えられます。
一方のスタイルクラスが他方を支配する場合、両方の値が保持されてプッシュダウンられますが、スタイルクラスの値が支配的であるため、他方のスタイルクラスの値は隠されます。
ただし、一部の子セルで、支配的なスタイルクラスが適用されていない場合(特別なスタイルプロパティが適用されていない場合)、他のスタイルクラスの値がこのプロパティの結果の値になります。
例: TODO という単語を含むコメントは、プレーンコメントよりも目立つようにスタイル設定する必要があります。コメントを表す言語の概念は、TODO 対応スタイル(TODO_Style)を適用する必要があります。これは、プレーンな Comment_Style に対する優位性を宣言します。ただし、実際のスタイリングプロパティは、コメントに TODO テキスト(isToDo())が実際に含まれている場合にのみ適用されます。それ以外の場合は、プレーンな Comment_Style プロパティが使用されます。

「優位性の追加」インテンションを使用して、domins over 句をスタイルに追加します。

セルアクション
すべてのセルモデルには、それに関連付けられたいくつかのアクションがあります。このようなアクションは編集の使いやすさを向上させるためのものです。任意のセルモデルのインスペクタで指定できます。
キーマップ
セルモデルのキーマップへの参照を指定できます。キーマップはルート概念です。キーマップ項目のセットで、各項目はキーストロークと実行するアクションで構成されます。特定のキーマップへの参照を持つセルモデルから生成されたセルは、キーストロークに対して適切なアクションを実行します。
キーマップでは、キーマップを適用できる概念を指定する必要があります。たとえば、式を使用して何らかのアクションを実行する場合は、適用可能な概念として Expression を指定する必要があります。その後、Expression の子孫のエディター宣言内に含まれるセルモデルに対してのみ、このようなキーマップを指定できます。それ以外の場合は、型エラーになります。
キーマッププロパティ「everyModel」が「true」の場合、このキーマップはエディターのすべてのセルに指定されているかのように動作します。これは、特定の概念の子孫が多数あり、それぞれにさまざまなエディターがあり、キーマップがその祖先に適用できる場合に便利です。「すべてのモデル」キーマップとしてマークすると、すべてのエディターでこのようなキーマップを指定する必要はありません。
キーマップ項目は次の機能で構成されます。
キーマップ項目がトリガーされたときに実行される関数 (何も返さない)
このキーマップ項目をトリガーするキーストロークのセット
キーマップ項目がここで適用可能かどうかを判断するブール関数 (指定されていない場合は、常に適用可能)。キーマップ項目がトリガーされた瞬間に適用できない場合は、アクションは実行されません。
キーマップ項目のキャレットポリシーを指定できます。キャレットポリシーは、このキーマップ項目を有効にするためにセル内のどこにキャレットを配置するかを指定します。キャレットポリシーは、最初の位置、最後の位置、中間の位置、任意の位置のいずれかになります。デフォルトでは、キャレットポリシーは「任意の位置」です。セル内のキャレットがトリガーされた瞬間にキーマップ項目のキャレットポリシーと一致しない場合、このキーマップ項目はアクションを実行しません。
アクションマップ
セルモデルには、アクションマップへの参照を含めることができます。アクションマップは、特定の概念に対するデフォルトのセルアクションをオーバーライドします。アクションマップは、いくつかのアクションマップ項目で構成されています。アクションマップでは、そのアクションマップが適用可能な概念を指定する必要があります。
アクションマップ項目には、次のものが含まれます。
文字列であるアクションの説明
アクションを実行する(何も返さない)関数。
アクションマップ項目は、デフォルトのアクションの 1 つをオーバーライドすることがあります(アクションを参照)。たとえば、エディターにアクションマップのない return ステートメントがあり、キーワード "return" を持つセルに対して Delete キーを押すと、ステートメント全体が削除されます。ただし、delete アクションマップ項目を含むアクションマップを指定することもできます。これは、return ステートメントを単に削除する代わりに、削除された return ステートメントと同じ式を含む式ステートメントで置き換えます。
アクション DELETE の説明: <description なし> 実行: (ノード、editorContext)-> void { ノード <ExpressionStatement> expressionStatement = node。new(ExpressionStatement) に置き換えます。; expressionStatement。式。set(node .expression); }
エディターのコンテンツ全体を選択し、Ctrl+A によってトリガーされる SELECT_ALL アクションも、アクションマップを使用してカスタマイズできます。executeWhile
メソッドを含む jetbrains.mps.nodeEditor.selection.SelectUpUtil
クラスを利用して、このアクションの上部選択境界を指定できます。

既存のアクションマップからのアクションマップ項目は、インポートによって新しいアクションマップで再利用できます。ユーザーには 2 つの選択肢があります。
アクションマップからすべての項目をインポートする
特定のアクション ID を持つアイテムのみをインポートします

インポートアクションは次の規則に従います。
インポート作業は推移的に行われます。
現在のセルのアクションマップで定義されているアクションは、インポートされたセルのアクションマップで定義されているアクションよりも優先されます。
複数のマップが同じ種類のアクションを定義している場合は、最後にインポートされたマップが優先されます。
循環インポートは許可されていません。
インポートされたセルアクションマップの適用可能な概念は、このマップの適用可能な概念の同じ概念または上位概念である必要があります。
アクションマップは言語間の作業をインポートします。ある言語のエディターアスペクトのアクションマップは、別の言語のエディターアスペクトからアクションマップをインポートできます。
DELETE と BACKSPACE アクションハンドラーは特定の意味を持ちます。アクションマップは定義や DELETE ハンドラーをインポートし、定義または BACKSPACE ハンドラーをインポートしない場合は、DELETE のためのものと同じデフォルト BACKSPACE ハンドラーが自動的に登録されています。
インポートされたアクションハンドラーの解決は動的です(実行時に行われます)。アクションマップ A がアクションマップ B から項目をインポートすると、登録される正確なアクションハンドラーはアクションマップ A の生成時に解決されません。その結果、アクションマップ B が変更されたときにアクションマップ A を再生成する必要がなくなります。
セルメニュー
特定のセルに対してカスタム補完メニューを指定することができます。セル宣言のインスペクタを開き、Common という名前のテーブルを見つけ、menu という名前の行を見つけ、新しいセルメニュー記述子を作成します。セルメニュー記述子はメニュー部分で構成されています。メニュー部分はさまざまな種類のもので、以下で説明します。
プロパティ値メニュー部分
このメニュー部分はプロパティセルで利用可能です。あなたのプロパティのために完成で示されるプロパティ値のリストを指定します。list <String> 型の値を返す関数を書くべきです。
プロパティ後置ヒントメニュー部分
このメニュー部分はプロパティセルで利用可能です。あなたのプロパティ値のための「良い」後置文字列として役立つ文字列のリストを指定します。そのようなメニュー部分では、list <String> 型の値を返す関数を書くべきです。このようなメニューは、MPS にプロパティの適切な値を「推測」させたい場合に便利です。たとえば、変数型名であるが最初の文字が小文字になっている、またはその型名で終わる良い変数名になると決めることができます。型 "Foo" の変数の場合、良い名前は "foo" になります。"," aFoo "," firstFoo "," goodFoo " などです。変数宣言用のエディターで、変数名のプロパティセルのメニューに次のようなメニュー部分を記述する必要があります。
プロパティの接尾辞のヒント接尾辞: (scope、operationContext、node)-> list <String> {list <String> result; node <タイプ> nodeType = ノード。タイプ ; if(nodeType!= null){result = MyUtil.splitByCamels(nodeType。getPresentation()); } else { 結果 = 新しいリスト <文字列> { 空 }; } 結果を返す ; }
ここで、splitByCamels() は、大文字で始まる文字列の接尾辞のリストを返す関数です(たとえば、MyFooBar-> MyFooBar、FooBar、Bar)。
一次置換子メニュー
これはセルメニューの一部で、子供のための主要なアクションを返します(デフォルトでは、セルメニューが存在しない場合と同様)。
参照メニューを選択する
これはセルメニューの一部で、参照先の主なアクションを返します(デフォルトでは、セルメニューが存在しない場合と同様)。
ノードメニューの置換 (カスタムノードの概念)
この種のセルメニュー部分は、編集されたノード(たとえば、完了メニューが呼び出されるノード)を特定の指定された概念およびそのサブコンセプトのインスタンスと置き換えることを可能にします。このようなセルメニュー部分は、たとえば、ノードのエディターの特定のセルにノード全体の置き換えを担当させる場合に便利です。たとえば、二項演算用のエディターを考えてみましょう。左オペランド用のセル、概念プロパティ "alias" 用のセルである演算符号用のセル、および右オペランド用のセルで構成されるすべてのバイナリ演算用の共通エディターがあります。
[> % leftExpression % ^{{ alias }} % rightExpression % <]
操作記号付きのセルのセルメニューを作成するのは当然です。これにより、操作記号を別の記号に置き換えることができます(もちろんノード全体を置き換えることによって)。そのような目的のために、操作記号のためのセルにノード置換メニュー部分を書くでしょう:
ノードを置き換える(カスタムノードの概念): BinaryOperation
BinaryOperation 概念のノードファクトリに従って、前の左子と右子が新しく作成された BinaryOperation に追加されます。
子メニューを置き換える (カスタム子供の概念)
そのようなセルメニュー部分は、ある子供のためのセルに適用可能であり、そのどのサブコンセプトが完成メニューに表示される(そして選択されたときインスタンス化されそしてインスタンスが子供として設定される)特定の概念を指定します。その概念を指定するために、ノード <ConceptDeclaration> 型の値を返す関数を書くべきです。
子メニューを置き換えます(カスタムアクション)。
この種のセルメニューパーツは、特定の子のセルに適用でき、子の概念だけでなく子の置換アクション全体をカスタマイズすることもできます。マッチングテキスト(補完メニューに表示されるテキスト)、説明テキスト(説明)補完メニューの右部分に表示されるアクション、および補完メニューからアクションが選択されたときに子ノードを作成する関数です。そのようなメニューを書くには、一致するテキスト、説明のテキストを指定し、ノードを返す関数を書く必要があります(このノードは、それぞれの子リンクで指定されたターゲット概念のインスタンスである必要があります)。
一般メニュー項目
この種のセルメニュー部分では、補完メニューでそれぞれのメニュー項目が選択されるときに MPS に任意のアクションを実行させることができます。メニュー項目にマッチするテキストを指定して、欲しいことをする関数を書くべきです。たとえば、クラスフィールドが存在しない場合、クラスフィールドの子リストセルを表示したくない場合があります。そのため、デフォルトのアクションを使用して新しいフィールドを作成することはできません。代わりに、クラスの新しいフィールドを作成するテキスト「create field」が一致する一般的なメニュー項目をクラスのエディターのどこかに作成できます。
テキストに一致する一般的なアイテム: フィールドハンドラーを追加: (ノード、モデル、スコープ、operationContext)-> void { ノード。フィールド。新規追加(<デフォルト>); }
アクショングループ
アクショングループは、カスタムアクションのグループを返すセルメニューパーツです。実行時には、メニュー構築中に、パラメーターオブジェクトと呼ばれる特定の型のオブジェクトがいくつか収集または作成されます。そのパラメーターには、アクショングループの関数オブジェクト型が対応するテキストと説明テキストを返すように指定されています。パラメーターオブジェクトを持つメニュー項目が選択されたときにトリガーされる機能も指定されています。
アクショングループの説明は次のもので構成されます。
パラメーターオブジェクト型。
指定された型のパラメーターオブジェクトのリストを返す関数(編集されたノード、スコープ、オペレーションコンテキストを取ります)。
指定された型のパラメーターオブジェクトを受け取り、一致するテキスト(補完メニューに表示されるテキスト)を返す関数。
指定された型のパラメーターオブジェクトを受け取り、パラメーターオブジェクトの説明テキストを返す関数。
完了メニューでパラメーターオブジェクトが選択されたときにアクションを実行する関数。
アクションを実行する関数は種類が異なる場合があるため、セルアクショングループのメニュー部分には 3 つの異なる種類があります。
一般的な行動グループ。パラメーターオブジェクトが与えられると、そのアクション関数は任意のアクションを実行します。パラメーターオブジェクトの他に、この関数には編集されたノード、そのモデル、スコープ、操作コンテキストが提供されています。
子グループを置き換えます。それは子セルに適用可能であり、パラメーターオブジェクトが与えられるとそのアクション関数は新しい子を返します。それはそれぞれの子リンク宣言で指定された型を持たなければなりません。パラメーターオブジェクトの他に、機能には編集されたノード、そのモデル、現在の子(たとえば置き換えられる子)、スコープおよび操作コンテキストが提供されます。
ノードグループを置き換えます。パラメーターオブジェクトが与えられると、そのアクション関数はノードを返します。通常、編集されたノード(つまり、完了メニューが呼び出されるノード)の一部です。パラメーターオブジェクトの他に、この関数には編集されたノード、そのモデル、スコープ、操作コンテキストが提供されています。
セルメニューコンポーネント
異なるセルのいくつかのメニュー部分が等しい場合は、重複を避けるために別々の固有のエンティティに抽出することをお勧めします。そのような目的のためにセルメニューコンポーネントが意図されています。セルメニューコンポーネントは、セルメニュー記述子(セルメニュー部分のコンテナー)と適用可能な機能の指定から構成されています。適用可能な機能の仕様は、メニューが適用可能である機能への参照(たとえば、子リンク宣言、参照リンク宣言またはプロパティ宣言)を含みます。たとえば、あなたのメニューコンポーネントがある子を置き換えるために使われるなら、その子リンク宣言はここで指定されるべきです。等
セルメニューコンポーネントが作成されると、セルメニューコンポーネントメニュー部分を介してセルメニューで使用できます。セルメニューコンポーネントメニュー部分は、特定のメニューコンポーネントへの参照を含むセルメニュー部分です。SModel 言語
参照表示のカスタマイズ
一致するテキストの指定および参照用のエディター内テキスト表現は、エディターの側面で直接行うことができます。
参照。プレゼンテーションセルでは、表示されるテキストをカスタマイズできます。

セルメニューでは、完了メニューに表示されるテキストをカスタマイズできます。

この機能は、以前は制約によって実現されていました。
参照制約におけるプレゼンテーションクエリの移行
制約の側面での参照プレゼンテーション部分の設計はその時代を示しているため、上記の新しい機能に置き換えられました。ほとんどのコードは自動的に移行されます。移行で生成された一部のコードは簡略化できるため、確認することを検討してください。
プレゼンテーションクエリを移行できない場合があります。参照リンクのあるコンセプトのエディターがあり、そのサブコンセプトの 1 つで参照用に定義されたプレゼンテーションパーツのある参照制約があるとします。エディターコンポーネントがサブコンセプトでオーバーライドされない場合、MPS はこのプレゼンテーション部分をインライン化する場所を認識しません。この場合、ユーザーコードでの未修正の参照プレゼンテーションを防ぐために、プレゼンテーションパーツの使用箇所を手動で移行する必要があります。それを行うにはいくつかの選択肢があります。
サブコンセプトでエディターを上書きするだけです。表示部分から適切な参照セルにコードを移動します。
参照セルを別のコンポーネントに抽出し、そのサブコンポーネントのコンポーネントをオーバーライドします。
参照用のプレゼンテーションを提供する新しい動作メソッドを作成します。作成したメソッドに参照セルデリゲートを作成します。このメソッドを subconcept でオーバーライドします。
言語が他の誰かによって他のプロジェクトで拡張されるかもしれないと期待しているなら、非推奨のプレゼンテーション部分を削除しないでください。そうでない場合は、拡張言語は不適切に移行されるかもしれません。
二段階削除
プロジェクティブエディターでは、削除またはバックスペースを押したときにコードのどの部分が削除されるかを射影するのが難しい場合があります。例: キャレットが baseLanguage ステートメントのセミコロン上にあり、Backspace キーを押すと、ステートメント全体が削除されます。2 段階の削除により、コードのどの部分が削除されるかを確認できます。ここではどのように動作します: ハイライト表示されますが削除または Backspace キーを押すと、削除されるコードの一部は、になります。必要に応じて、 もう一度 Delete キーまたは Backspace キーを押すと、コードが削除されます。ハイライトした後、このコードを削除したくないことに気付いた場合は、エスケープを押すか、キャレットを動かすだけでハイライトが消えます。
例を見てみましょう。キャレットをステートメントのセミコロンに置きます。

Backspace キーを押します。ステートメント全体がハイライトされます。これは、Backspace キーをもう一度押すと、ステートメントが削除されることを意味します。

もう一度 Backspace キーを押します。ステートメントが削除されます。

他のノードでも同じことがデフォルトで機能します。
2 段階削除を有効にするには、設定> エディター> 一般の 2 段階削除チェックボックスをオンにします。
コードからの 2 段階削除
言語設計者は、カスタム削除アクションに 2 段階の削除シナリオを含めることができます。そのために、jetbrains.mps.lang.editor の ApproveDelete_Operation が導入されています。この操作はノードに適用されます。

この操作は、それが成功し、そのノードが以前に削除を承認されていない場合に true を返します。より正式には、以下のすべての条件を満たす必要があります。
1)2 段階の削除設定オプションがチェックされています。
2)ノードが完全に選択されていません。
3)ノードはすでに削除承認されていません。
これらの条件がすべて満たされると、削除が承認されたノードがハイライトされ、カスタム削除アクションがこの時点で停止することがあります。
削除を承認した直後に同じカスタム削除アクションが呼び出された場合、approveDelete 操作は false を返し(ノードがすでに承認されているため)、アクションは削除を続行します。
baseLanguage の典型的なシナリオを見てみましょう。

これは、ドット式操作の削除アクションの一部です。このアクションは、最初に削除の操作を承認しようとし、成功するとアクションが停止します。ir が成功しない場合、ノードの操作がすでに承認されている(= ハイライトされている)か、ユーザーがノードを選択したか、「2 ステップ削除」設定オプションがオフになります。この場合、操作を削除し、抽象概念のノードに置き換えます。
より複雑なケース
カスタマイズされた削除アクションは、現在のノードを削除するよりも複雑な場合があります。
シナリオ例を見てみましょう。IncompleteMemberDeclaration の「final」キーワードで Delete キーを押します。final プロパティを false に設定するカスタムアクションがあります。 エディターには、ノードの final プロパティが true の場合にのみ表示されるセルがあります。そのため、アクションの後、セルは表示されません。
(final プロパティを false に設定して)非表示にする前に final キーワードをハイライトする場合は、次の方法で削除を承認します。

エディターセルの選択
プログラムで特定のセルを選択するには、jetbrains.mps.lang.editor 言語の select 構成要素を使用できます。
いくつかの注意事項:
すべてのパラメーターを指定する必要はありません。
editorContext 値は常に指定する必要があります。
「セル」の値は、ID (エディター定義で指定されている場合)、プロパティ参照、式で指定されたプロパティとして指定できます。
「セル」は、「FIRST」、「LAST_EDITABLE」など、使用可能な定義済み値のいずれかで指定することもできます。
選択インデックスの値 -1 は「最後の」位置を意味します。
完成品のカスタムスタイルと優先順位 (実験用)

言語設計者は、完了メニューの項目のスタイルと優先順位を設定できます。そのためには、言語設計者は、言語のエディターの側面で CompletionStyling ルートを作成する必要があります。補完メニュー項目のスタイルを指定するには、言語設計者は最初に項目を指定する必要があります。
現在、完了アイテムの 2 つの可能なセレクターを提供しています。
特定の概念のインスタンスを変更するアイテム。このセレクターは、ユーザーがコンセプト (またはそのプロパティ、参照、子) のノードにキャレットを置き、Ctrl + Space キーを押したときに補完メニューに表示される項目を選択します。
特定の概念のインスタンスを作成するアイテム。これらは主に代替アクションです。例: ユーザーが StatementList にある ReturnStatement を選択し、Control + Space を押すと、完了メニューの項目が Statement のインスタンスを作成し、ReturnStatement をそれらのインスタンスに置き換えます。Statement のインスタンスを作成するアクションのセレクターは、それらのアイテムを選択します。
1 つの項目を複数のセレクターによって選択できることが重要です。例: 上記の状況では、複数のセレクターが 1 つの補完項目に一致します。
ステートメントのインスタンスを作成するアクションの場合 (アイテムが現在のノードを別のステートメントに置き換えるため )
ステートメントのインスタンスを変更するアクションの場合 (現在のノードは ReturnStatement であり、これはステートメントでもあるためです。)
StatementList:statement のインスタンスを変更するアクションの場合 (メニュー項目は新しいノードを親 StatementList のステートメントロールに貼り付けるためです )
可能な限り最も具体的なセレクターを選択する必要があります。例: BaseConcept のインスタンスを変更するセレクターまたはアクションは、最も具体性の低いセレクターであり、すべての補完メニュー項目に影響します

セレクターがメニュー項目と一致すると、言語デザイナーはそのスタイルをカスタマイズできます。スタイルオブジェクトはこの目的を果たします。
現在、次のことが可能です。
アイテムのフォントを太字にする
アイテムのフォントを斜体にする
アイテムのテキストを削除する (概念を廃止できます)
アイテムの背景とテキストの色を設定します
アイテムを隠す
アイテムの優先順位を設定します
すべてのスタイルが累積することに注意してください。
少なくとも 1 つのスタイラーが太字 / 斜体 / 非表示スタイルのいずれかを設定している場合、項目は太字 / 斜体 / 非表示になります。
背景色またはテキストの色が矛盾する場合は、最初に指定された色が使用されます。
優先順位は項目をソートするために使用されます。スタイルによってアイテムの優先順位として設定された最大値が使用されます。
アイテムはまず優先度順にソートされ、次にユーザーのテキストと一致するレベル順にソートされます。現在、このレベルを上書きする方法はありません。
言語設計者が使用できるいくつかのパラメーターがあります。それらはアイテムに格納されています。
情報パラメーター:
matchingText - アイテムの左側に表示されるテキスト。このテキストは、ユーザーが補完メニューにテキストを入力したときにアイテムをフィルター処理するために使用されます。
descriptionText - アイテムの右側に表示されるテキスト。
parameterObject - 一部の項目はオブジェクトでパラメーター化できます。例: ノードの参照を変更する項目は、実行時に設定される参照のターゲットでパラメーター化されています。
outputConcept - 代替アクションが新しいノードを作成するようないくつかのアクションは、出力の概念は新しいノードの概念です。
baseLanguage のスタイルのいくつかの注目すべき例:
ReturnStatementStyling は、戻り項目を太字にし、現在のステートメントリストの最後にある場合、その優先度をゼロ以外に設定します。
アイテムが変数宣言を参照する場合、アイテムの優先度をゼロ以外に設定する VariableReferencePriority。
重要な注意点:
この機能は実験的なものであり、その設計は将来大幅に変更される機能があります。この機能に関するフィードバックは非常に高く評価されており、それを改善できます。この機能をオフにする可能性があります: 設定 - > エディター - > 一般 - > Use completion styling
関連ページ:

エディタークックブック
このドキュメントは、上級言語設計者を対象としており、MPS エディターに関する最も一般的な質問に対する回答を提供します。エディターのドキュメントを読むのを好むかもしれません。それはサブジェクトに関する徹底的な情報を含みます。エディター定義を作成する方法:MPS がエディターをデザインするために言語デザイナーに提供する DSL は、セルの概念に基づいて構築されています。言語設計者は、エディターセルを組み合わせて、表記法の望ましい最終レイアウトを反映するように画面上に配置します。画面の右下隅にある...

インスペクター
インスペクターウィンドウには、メインエディター領域で選択されたノードに関連する追加情報が表示されます。これにより、言語設計者は、一部の、通常は重要性の低いエディター要素をメインエディターからオフロードして、エディターの煩雑さやノイズを減らすことができます。エディター定義やジェネレーターマクロなどの一部の MPS 組み込み言語は、インスペクターウィンドウに大きく依存しています。インスペクターウィンドウには、メインエリアで選択されたノードのコンセプトの名前が常に表示され、コンセプト宣言を開くためのリ...

コンテキストアシスタント
概要:MPS はコンテクストの中でアクションを実行するためのいくつかのメカニズムを提供します: 完了、インテンション、リファクタリング、他の様々なポップアップメニュー。これらのメカニズムには、経験の浅い新規ユーザーにはすぐには見えないという共通点があります。彼らはまた、多くの可能な選択肢を提供し、利用可能な機能全体を明らかにします。これは上級ユーザーを手助けしますが初心者を圧倒するかもしれません。DSL でスクリプトを作成するプロセスを通じて新しいユーザーをより適切にガイドするために、コンテキ...

エディターのアクション
MPS エディターには、完了アクション、ノード作成ポリシーにかなり実用的なデフォルトがあります。しかし、カスタマイズしたい場合は、アクション言語を使用しなければなりません。ノードファクトリ:あるノードが別のノードと交換されるとき、交換されるノードによって保持される値で交換するノードの作成プロセスをパラメーター化すること、またはおそらくモデル内の交換するノードの将来の位置を反映することも役に立つでしょう。ノードファクトリはあなたにまさにそれを与えます。新しいノードを代入アクションで、または新しい...

テスト言語
テスト言語:導入:テストは言語設計者の作業の重要な部分です。MPS が優れているためには、BaseLanguage コードと言語の両方のテスト機能を提供する必要があります。jetbrains.mps.baselanguage.unitTest 言語を使用すると、JUnit-like ユニットテストで BaseLanguage コードをテストできますが、言語テスト言語の jetbrains.mps.lang.test は、言語テストを作成するための便利なインターフェースを提供します。クイックナビゲーション...

構造
MPS を使用すると、目的の言語の文法を定義する必要がなくなるため、言語の構造を指定するためのさまざまな方法が明らかに必要になります。ここで構造言語が役に立ちます。それはあなたに言語構造を定義するためのすべての手段を与えます。前に説明したように、MPS でコーディングする場合、AST を直接効果的に構築しているため、言語の構造では、AST の構築に使用する要素であるブリックを指定する必要があります。プロパティ、参照、および子供: レンガをコンセプトと構造言語が公開の概念と概念インターフェースだけ...