そのため、ASで記述された小さなモジュール(異なる引用符で囲まれた2行)、言語myLanguages.escapedStringsがあります。ここでは、 意図の側面に関連する自動化用のスクリプトは2つのみです。 -二重引用符で囲まれた文字列。
おそらくこのコードの実装は理想的とは言えませんが、これはタスクに対するシンプルで効果的なソリューションの有効な例です。Intentions言語を使用すると、エディターに新しい機能を簡単に追加できます。 同じパスをわずかに異なる方法で実装できますが、最も速く最も簡単なのは意図です 。
わずかな悲しみで、多数のスラッシュで味付けされた実験ラインを見てください。 一方では、問題は解決されますが、他方では、それはどういうわけかい、間違っています。 文字列をそのままにして、「不正な文字列リテラル」エラーを引き起こさない簡単な方法を提供しないのはなぜですか? これ以上簡単なことはありません。 他の言語にも同様の機能があることを思い出してください-たとえば、そのような言語のC#には、ActionScriptの言語拡張として移植するのに適した便利な@ "..."コンストラクトがあります。
RASEでは、アプリケーションのソースコード(使用されるすべての拡張子を考慮に入れて)が最初にジェネレーターによって処理され、ActionScriptコンパイラーが理解できるソースコードが作成されることを忘れないでください。 つまり、文字列を変更せずに作業できますが、生成時にのみ自動シールドが行われます。
ステップ1.仕事のために、仲間!
新しい式を作成する必要があります。 これを行うには、言語拡張機能に移動し、 構造の面で新しい概念を作成します。
コンセプトの名前-EscapedStringを入力します。
次の質問は、どのエンティティを拡張するかです。 それに答えるために、少し研究を試みることができます。 文字列が二重引用符で囲まれている場合はStringLiteral型であり、単一引用符で囲まれている場合はStringApostropheLiteralです。 この仮定は、行のコンテキストメニューを呼び出して[概念宣言に移動 ](MacのCtrl-Shift-SまたはCmd-Shift-Sショートカットに相当)を選択することで簡単に確認できます。
EscapedStringがどのコンセプトを展開するかを最終的に決定するために、 StringLiteralBaseタイプのコンテキストメニューをもう一度見て、オブジェクトの階層内でどのように見えるかを見てみましょう。
StringLiteralとStringApostropheLiteralが子であるStringLiteralBase自体がExpressionから継承し、IStringLiteralインターフェイスを実装していることがわかります。
StringLiteralBaseコンセプトの構造とメソッドを検討した後、 IStringLiteralインターフェイスでExpressionを継承し、 StringLiteralBaseで同じレベルに到達することにしました。 未完成のルートに戻り、入力します( Ctrl-Spaceによる「スマート」オートコンプリートでサポートされているスペルに注意してください):
階層のあるウィンドウでは、表示されたツリーに変更がすぐに反映されます。
続けて。 次のステップでは、同じウィンドウにエイリアスをエイリアスに追加します。 オートコンプリートに使用されます(コードにデザインを追加するには、ユーザーは「@」文字を入力する必要があります)。 同じ目的で、 shortDescriptionを追加します (これは、自動クックメニューのエイリアスの右側の説明です)。
ステップ2.エディターの作成
エディターの作成に進みます(次のタブで)。
その中に、引用符が@記号になる前に、引用符の値で囲まれた将来の構造を視覚的に表現します。
スクリーンショットの定数は、プレーンテキストが格納される特別なセルです。 「Const」と「ctrl + space」は、エディターを作成するときにすぐに頻繁に実行されるアクションになります。
別のセル( Enter )を追加し、オートコンプリートのリストから「{値}」を選択します
別の定数引用符を追加します。
この段階で、新しいモジュールを初めてコンパイルすることは理にかなっています。 Ctrl-F9 ( Cmd + F9 )を押すか、メインメニューで[ ビルド]> [モジュールの作成]を選択し、 メイン()に移動して、新しい行を含む例を作成します。
@記号で始まるテキストを入力します(最初のステップの最後にある構造セクションのエイリアスを使用して設定されたオートコンプリートは既に機能しています)が、デザインがまったく予想外に奇妙に見えることがわかります。
ステップ3.順序を復元する
不要なスペースを削除するには、エディターが作成されたタブに戻り、各要素のスタイルが表示されるインスペクターウィンドウに注意を払います。 デザインの各要素には独自のプロパティセットがあることに気付くかもしれません。
@と開始引用符の間のスペースを削除します。 これを行うには、「犬」記号を選択し、次のプロパティを基本スタイルに追加します。
引用を行うときに自転車のさらに別の発明に煩わされないようにするために、すでに動作しているコードを調べ、これがStringLiteralBaseの同様のタブでどのように行われるかを見ることができます。
そこで、これらのスタイルはそれぞれ StringQuotationOpenとStringQuotationCloseと呼ばれます 。 それらをコードにコピーします。 そして、次の構造は、ソースの値フィールドのプロパティを担当します。
ここでも、言語拡張モジュールをコンパイルして、 Main()クラスに移動します。 完全に異なる問題!。
ステップ4.コード生成
ここで、式が生成されるASコードを見ると面白いでしょう。 エディターのコンテキストメニューから、[ 生成(廃止)]> [現在のモデルからテキストを生成 ]を選択します(ところで、メインメニューの[ ビルド]セクションの下部で同じアクションを使用できます)。
生成されたコードは、 出力ウィンドウの画面の左下隅に表示できます。 そこで何が見えますか?
「 TexGen not found 」というメッセージは、エディターが言語拡張に一致するジェネレーターを見つけられないことを意味します。 そうそう:まだ書いていません。
拡張のすべての新しい側面を作成したのと同じ方法で、新しいジェネレーターを追加します。 通常、ジェネレーターの名前は、コードを変換するターゲット言語の名前によって選択されます。 私たちの場合、この言語はActionScriptです。
明らかに、名前自体はその目的を示していないため、コンテキストメニューからこのアスペクトのプロパティに移動し、( 依存関係)タブの下部ウィンドウ(フルパスジェネレーターのプロパティ>依存関係>ジェネレーターに依存)でActionScript言語への依存を示します。
ジェネレータープロパティの3番目のタブでは、プロジェクト全体のコード生成チェーンのどの段階で使用するかを示します。 私たちの場合、ActionScriptの前 。
設定が設定されたら、ジェネレーターのロジックの説明を開始できます。 ルートEscapedStringに戻ります。 [ ジェネレータ ]タブの空のフィールドをクリックして、 テンプレート宣言を呼び出します。
私たちの目には2つのタブが開かれます。最初のタブはmainと呼ばれ、2番目のタブはreduce_EscapedStringです。 ご想像のとおり、最初のものには構築の一般的な規則が含まれ、2番目には直接操作が含まれています。
reduce_EscapedStringタブに移動し、次の構成を挿入します。
通常の文字列のコードを取得します。
テンプレートフラグメント ( Ctrl-Shift-Fキーの組み合わせまたはAlt-Enterドロップダウンメニューから利用可能)、これは生成されたコードに挿入するコードまたはテキストです。
線の周りにジェネレーターテンプレートアノテーションが現れました。
次に、生成された行に値を入力する必要があります。そのために、行にプロパティマクロを追加します ( node.valueのインテントリストから既製のテンプレートを選択します)。
その結果、モジュールをコンパイルしてMain()からコードを生成する場合、次のような半製品が得られます。
ご覧のとおり、ジェネレーターは現在、プレーンな非スクリーンテキストを削除しています。
スクリーニング機能を追加するには、 「$」記号にカーソルを置き、 インスペクターウィンドウを開きます。 生成中に文字列の値を変更するコードの記述を開始します。
ただし、 EscapedStringコンストラクト自体にメソッドを作成し、マクロから呼び出す方がよいため、スクリーニングプロセス全体をプロパティmacroで説明しません。 概念のメソッドを作成するために、 Behaviorアスペクトが特別に設計されています。このアスペクトでは、 escape()メソッドを作成します。
ステップ5.行動の側面
ここで、 escape()メソッドをコンセプトに追加する必要があります。
言語myLanguages.escapedStringsのコンテキストメニューを使用した通常のジェスチャにより、 Behaviorアスペクトをプロジェクトに追加します。
私たちのタスクは、出力に必要なすべてのスラッシュを含む有効な文字列を取得することです。
これを強調します。 value 、リファクタリングメニューの対応するアイテムを使用するか、キーボードショートカットCtrl-Alt-V ( Cmd-Alt-V )を使用して、メソッドが出力するローカル変数resultに変換します。
タスクを複雑にしないために、前の記事で示したIntentionsの例の作業コードで作業します。 このエディターには、キーボードショートカットCtrl-E( Cmd-E )があり、最近開いたファイルのリストがウィンドウに表示されます。
さらに苦労せずに、コードの行をあるルートから別のルートにコピーします(コピーするとき、RASEはインポートについて問い合わせてきますが、 Import Noneを選択します)。 プロジェクトをゼロから作成し、トレーニングプロジェクトに基づいていない場合は、ショートカットCtrl-L ( Cmd-L )を使用してRegexp言語をインポートすることを忘れないでください。
その結果、いくつかの修正後、ソースコードは次のようになります。
結果のコードが機能するためには、 ジェネレーターのアスペクトに戻るだけで、インスペクターのノードを変更する必要があります。 ノードの 値 。 escape() 。
モジュールをコンパイルし、ActionScriptを生成して結果を確認します。
手順6.ノードウィンドウの入力
教育用言語拡張機能の作成にはある程度の成功を収めましたが、結果がやや奇妙になったことに気づかざるを得ません。 なんで? 文字列はまだほとんど実用的ではないため、よく見ると、現在の中間結果では文字列( 文字列型)を取得できませんでしたが、一般的には何が明確ではありません 。 それを信じないでください-隣接する「普通の」行に対して最初にいくつかのアクションを呼び出そうとすることによって、自分で見てください...
...そして、私たちのもの:
文字列の不自然な本質を確認するには、型システムウィンドウ( Ctrl-Shift-TまたはCmd-Shift-T )を呼び出して、式に型がないことを確認します。
型システムは、特に初心者プログラマーにとっては簡単なフィールドではありません。 型システムは、要素の相互作用と相互依存のルールを定義するセマンティックレイヤーを作成します。 動物世界の分類との類推により、特定の関係を持つさまざまなエンティティ、たとえば「象」、「犬」、「動物」などが存在します。 (この場合、「象」と「犬」はどちらも「動物」ですが、「象」は「犬」ではありません)。
さまざまなコンテキストでの文字列の動作をより予測可能(かつ有用)にするには、適切な型にキャストする必要があります。 私たちの生活を複雑にしないために、私たちは再びトリックに行き、「本物の」ラインのタイプシステムの側面の特性を覗いてみます。
お気に入りのStringLiteralBaseのコードでブックマークを開くと、次の構造が見つかります。
ええ、表現されているエンティティがString型であると言っているかのように、 Intentionルールがあります。 特別な引用言語を使用します。これにより、たとえばActionScriptやMXMLコードを埋め込むことができ、コンパクトさとセマンティクスを実現できます。
学習言語でTypesystemアスペクトを作成します。
Ctrl-L (またはCmd-L )を使用して見積言語をプロジェクトにインポートし、言語拡張でまったく同じロジックを再現します。
メソッドの本文では、 StringLiteralBaseとの類推により、以下を再現します。
次に-これは重要です-ClassifierTypeを挿入します...
キーボードショートカットCtrl-R ( Cmd-R )を使用して、モデルのインポートを呼び出します。
最後に、 Stringを追加できます。
参考:このようなコードは、 Quotation拡張機能を使用しないこのコードのように見えます。
モジュールをコンパイルできます-これで、エンティティがActionScriptタイプシステムでその場所を見つけました。
ステップ7.左変換
その間、この記事で言及すべきことがいくつかあります。 ステップ1の最後で、式にエイリアスを設定します。
エディターにはさらに2つの重要な動作があります-これらは左と右の変換です(RASEに関する入門記事でそれらについて詳しく知ることができます)。 簡単に言えば、通常の文字列をエスケープされた文字列に変えるようにエディターに教える必要があります。
変換メニューアクションコマンドを使用して、 アクションの新しい側面を言語に追加します 。
このエンティティにmakeStringEscapedという名前を付けて 、編集を開始します。 StringLiteralBaseからEscapedStringへの左側の変換に興味があります。
簡単なアイテムを追加して、次のテンプレートへの入力を開始します。
その結果、次のコードのようなものが得られるはずです。
プロジェクトをコンパイルできます。 @文字を任意の行に追加すると、すぐにEscapedStringに変わります。
@を削除するときに、反対のアクション(エンティティEscapedStringを元の文字列に変換する)を追加します。
ステップ8.エディターの動作を改善する
エディターに移動します。エディターには、特定のデザインが既にあります。
特定のキーワードを追加する必要があり、削除すると逆変換が発生します。 [ 新規作成]> [セルアクションマップ]を選択します 。
次に、delete @イベントを処理する方法を学習する必要があります。 2つの方法があります-複雑(キーボード入力のインターセプト)と単純( アクションマップ )。
選択肢がほとんどないため、[ 削除]を選択し、 EscapedStringをStringLiteralに置き換えるコードを入力します。
次のタブで、 @記号を含むフィールドを選択して、 インスペクターウィンドウでアクションマップを割り当てます。
変換を完全に機能させるために、 editable:falseパラメーターを隣接フィールドのプロパティ(開始引用符)に追加します。
言語拡張の学習は完全に準備ができています。
9.結論
この記事を読んだ後、言語拡張機能の作成が平均的な開発者にとって非現実的なものでなくなることを願っています。 言語構成を作成せずに、小規模から始めてインテンションを通じて作業を自動化できます。 そして、自信と本当のニーズがあるとき、あなたはあなた自身の言語とDSLを書き始めることができます。 MPSプラットフォームでの作業の簡単な原則を理解し、それをナビゲートし、他の言語で既製のソリューションを見つけることが重要です。 次の記事では、このトピックをさらに詳しく明らかにします。