その結果、 NetBeans IDE用のプラグインが作成されました。これは、私の意見では(Eclipseとともに)最高のオープンソースIDEの1つです。 それでも、NetBeans Plaformのモジュールとプラグインの開発方法に関する情報はかなり散在しており、ロシア語には事実上何もありません。
言語のパーサー
NetBeansで新しい言語をサポートするために最初に必要なことは、その言語の字句解析プログラムを作成することです。 それらを自分で作成するか、何らかのツールを使用してこれを行うことができます。 ツールには、たとえば次のものがあります。
- JavaCC -Java言語のパーサージェネレーター。
- ANTLRは、多くの言語用のパーサージェネレーターです。
- Bison-パーサージェネレーター。
- Yacc-パーサージェネレーター。
- 他の多くのパーサー
プラグインを実装するために、最も一般的なANTLRv3の 1つとしてANTLRを選択しました 。 Javaコードを生成できるため、NetBeansプラットフォームのプラグインに比較的簡単に統合できます。
ANTLRの場合、LL文法を使用して言語の説明を記述する必要があります。 この言語はRBNFに近く、ほとんど直感的です。
簡略化するために、ANTLR文法の説明は、レクサーと文法の2種類の規則で構成されています。 レクサールールは、字句解析の段階で分析されるトークンを記述します。 レクサー規則名は大文字で、文法規則は小文字です。
レクサールールの例:
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
このルールは、ソースコード内の識別子、つまりラテン文字またはアンダースコアで始まり、数字、ラテン文字、またはアンダースコアをそれぞれ含まない単語を強調表示します。 文字シーケンスに一致するすべてのレクサールールがトークンに割り当てられます。
トークンの解析後、解析が実行され、 抽象構文ツリーまたはASTが生成されます 。 文法ルールは、ASTの生成に使用されます。
文法規則の例:
try_statement : TRY block (catch_clause)* (finally_clause)?;
このルールは、try ... catchブロックを記述します。 ルールは、トークンのシーケンスおよび/または他の文法ルール名で構成されます。 この場合の記号「*」は、catch_clause括弧内のブロックが数回繰り返されるか、存在しないことを意味します。 文字「?」 -finally_clauseブロックは1回のみ存在する場合と存在しない場合があります。
おそらくこれはANTLR言語で終わり、サイトにはドキュメントと多くの例があります。 同じ場所に、ルールのデバッグに役立つANTLRWorksがあります。 逆アセンブルされたツリーをグラフィカルでかなり視覚的な方法で表示します。
githubのプラグイン用に作成されたVala言語の構文のANTLRの説明を参照してください
NetBeansのモジュール
1)プロジェクトを作成する
最初に、新規プロジェクトからNetBeansモジュールプロジェクトを作成する必要があります| NetBeansモジュール| モジュール [スタンドアロンモジュール]チェックボックスをオンにします。 プロジェクトの正しい名前、モジュールの名前を指定し、「XMLレイヤーの生成」ボックスをチェックする必要があります。 最後のアクションは、プラグインの動作とモジュールの他のパラメーターを実装するクラスの名前を含むlayer.xmlファイルを作成します。
2).valaおよび.vapiファイルのサポートをモジュールに追加します
NetBeansは、 Datasystems APIおよびFilesystems APIを介してプロジェクトファイルを処理します 。 プロジェクトのルート要素を選択して、新しい拡張機能のサポートを追加できます。 その他| モジュール開発| ファイルの種類。
これらのアクションは、DataObjectを操作するための単純なクラスの作成につながります。この場合はValaDataObjectであり、このクラスは.valaファイルハンドラーとしてlayer.xmlに登録されます。
< filesystem >
< folder name ="Loaders" >
< folder name ="text" >
< folder name ="x-vala" >
< folder name ="Actions" >
...
</ folder >
< folder name ="Factories" >
< file name ="ValaDataLoader.instance" >
< attr name ="SystemFileSystem.icon" urlvalue ="nbresloc:/org/carbonfx/valaproject/vala.png" />
< attr name ="dataObjectClass" stringvalue ="org.carbonfx.valaproject.ValaDataObject" />
< attr name ="instanceCreate" methodvalue ="org.openide.loaders.DataLoaderPool.factory" />
< attr name ="mimeType" stringvalue ="text/x-vala" />
</ file >
</ folder >
</ folder >
...
* This source code was highlighted with Source Code Highlighter .
構文の強調表示
これで、新しい言語のモジュールに構文の強調表示を追加するすべてができました。
1)ANTLRによって生成されたパーサーファイルをモジュールに接続します
ANTLRで記述されたパーサーがあり、Netbeansのモジュールに接続できます。 これを行うには、ANTLRWorksでレクサーファイルとパーサーファイルを生成し、プロジェクトに追加します。 生成されたファイルのパッケージを指定できます。
@header { package org.carbonfx.valaproject.antlr; }
@lexer::header { package org.carbonfx.valaproject.antlr; }
* This source code was highlighted with Source Code Highlighter .
2)ANTLRアナライザーをNetBeans APIに適合させます
最初に、抽象クラスorg.netbeans.spi.lexer.LanguageHierarchyを実装する必要があります。 実際、このクラスは言語をトークンの形で定義します。トークンはカテゴリに分けられます。 カテゴリは、構文の強調表示を実装するためだけに必要です。
public class ValaLanguageHierarchy extends LanguageHierarchy<ValaTokenId> {
@Override
protected Collection<ValaTokenId> createTokenIds() {
return Arrays.asList(tokens);
}
@Override
protected Lexer<ValaTokenId> createLexer(LexerRestartInfo<ValaTokenId> lri) {
return new org.carbonfx.valaproject.lexer.ValaLexer(lri);
}
@Override
protected String mimeType() {
return "text/x-vala" ;
}
static synchronized ValaTokenId getToken( int id) {
return idToToken. get (id);
}
private static final Map<Integer, ValaTokenId> idToToken = new HashMap<Integer, ValaTokenId>();
private static final ValaTokenId[] tokens = new ValaTokenId[] {
token(ValaLexer.AND, "operator" ),
token(ValaLexer.AND_ASSIGN, "operator" ),
token(ValaLexer.BACKSLASH, "operator" ),
// ...
token(ValaLexer.UNICODE_CHAR, "error" ),
token(ValaLexer.OTHER_CHAR, "error" ),
token(ValaLexer.UNKNOWN_CHAIN, "error" ),
};
static {
for (ValaTokenId token : tokens) {
idToToken.put(token.ordinal(), token);
}
}
private static ValaTokenId token( int antlrToken, String category) {
return new ValaTokenId (ValaParser.tokenNames[antlrToken], category, antlrToken);
}
}
* This source code was highlighted with Source Code Highlighter .
ここでValaTokenIdの実装を見逃した、 それは非常に簡単です
クラスを作成します
ValaLexer
ValaLexer
、
Lexer<ValaTokenId>
インターフェースを実装します。
ValaLexer
クラスの主な目的は、入力で一連の文字を受け取り、一連のトークンを返すことです。 最も単純な実装では、コンストラクタに文字のシーケンスを保存し、
nextToken()
メソッドでトークンの戻り値を順番に実装するだけで十分です。
ここで
CharStream
う1つのポイントは、ANTLRクラスが受け入れるストリーム、つまり
CharStream
インターフェースにNetBeansプラットフォームが提供する文字のストリームを適応させる必要があるということです。 幸いなことに、同様のプロジェクトにはこのクラスの既製の実装が既にあります。
3)バックライト構成
FontAndColors.xmlファイルを作成します。このファイルでは、さまざまな要素の色で強調表示されたカテゴリへのトークンのカテゴリ(上記)の対応を記述します。 特に、ファイルは次のとおりです。
<? xml version ="1.0" encoding ="UTF-8" ? >
<! DOCTYPE fontscolors PUBLIC "-//NetBeans//DTD Editor Fonts and Colors settings 1.1//EN" "http://www.netbeans.org/dtds/EditorFontsColors-1_1.dtd" >
< fontscolors >
< fontcolor name ="character" default ="character" />
< fontcolor name ="error" default ="error" />
< fontcolor name ="identifier" default ="identifier" />
< fontcolor name ="keyword" default ="keyword" />
< fontcolor name ="comment" default ="comment" />
< fontcolor name ="number" default ="number" />
< fontcolor name ="operator" default ="operator" />
< fontcolor name ="string" default ="string" />
< fontcolor name ="separator" default ="separator" />
< fontcolor name ="whitespace" default ="whitespace" />
< fontcolor name ="method" default ="method" />
< fontcolor name ="javadoc" default ="javadoc" foreColor ="ff006666" />
< fontcolor name ="regex" default ="regex" foreColor ="ff660066" />
< fontcolor name ="command" default ="command" foreColor ="ff006633" />
</ fontscolors >
* This source code was highlighted with Source Code Highlighter .
Bundle.propertiesファイルでは、カテゴリの人間の名前を記述します。
operator=Operator
string=String
separator=Separator
whitespace=Whitespace
method=Method
regex=Regular Expression
command=Command
...
* This source code was highlighted with Source Code Highlighter .
次に、ソースコードValaExample.valaを含むサンプルファイルをプロジェクトに追加します。 NetBeansトークンの色設定ダイアログに表示されます。 最後のステップ-強調表示のためにlayer.xmlファイルに行を追加します:
< filesystem >
< folder name ="Editors" >
< folder name ="text" >
< folder name ="x-vala" >
< file name ="language.instance" >
< attr name ="instanceCreate" methodvalue ="org.carbonfx.valaproject.lexer.ValaTokenId.getLanguage" />
< attr name ="instanceOf" stringvalue ="org.netbeans.api.lexer.Language" />
</ file >
< attr name ="SystemFileSystem.localizingBundle" stringvalue ="org.carbonfx.valaproject.Bundle" />
< folder name ="FontsColors" >
< folder name ="NetBeans" >
< folder name ="Defaults" >
< file name ="FontAndColors.xml" url ="FontAndColors.xml" >
< attr name ="SystemFileSystem.localizingBundle" stringvalue ="org.carbonfx.valaproject.Bundle" />
</ file >
</ folder >
</ folder >
</ folder >
</ folder >
</ folder >
</ folder >
< folder name ="OptionsDialog" >
< folder name ="PreviewExamples" >
< folder name ="text" >
< file name ="x-vala" url ="ValaExample.vala" />
</ folder >
</ folder >
</ folder >
</ filesystem >
* This source code was highlighted with Source Code Highlighter .
あなたがすべてを正しく行い、私が何も見逃していなければ、プロジェクトをコンパイルして実行できます。 拡張子が.valaのファイルを開くと、キーワードが目的の色で強調表示されていることがわかります。 Vala言語が設定ダイアログに表示され、ValaExample.valaファイルの強調表示されたコンテンツを選択して表示できます。
おわりに
それがすべて終わった後、構文の強調表示ができました。 ただし、ANTLRを使用して作成されたアナライザーは、他のタスクに使用できます。
- コードの検証と誤った構造の強調表示。
- 自動インデント;
- メソッド名、関数引数のツールチップ。
現在まで、Vala自体のプラグインには最初の2つのポイントが実装されています。 将来は、インデントのサポートと誤った構造の強調表示をプロジェクトに追加する方法を説明しようとします。
また、ANTLRを使用せず、Valaで記述されたパーサーを使用してValaコードを解析しようとする考えもありました。 具体的には、Valaコンパイラ-libvalaで使用される実装です。 プラグインの改良への接続に興味がある人は、書いてください!
参照資料
- githubのプロジェクトのソースコード 、コンパイルされたモジュールをダウンロードすることもできます
- ANTLRおよびANTLRWorksのWebサイト
- NetBeans + ANTLR用のプラグインを作成する手順
- NetBeans + JavaCCのプラグイン作成手順