私がレキシングしている言語には、ランタイム構成に応じてキーワードをホットスワップする機能が必要です。ANTLR4動的トークンタイプ
それはあなたの文法(Java)の中でターゲット固有のコードを埋め込むので、限り、あなたはOKですとしてこれを行う方法は比較的簡単です:
lexer grammar LanguageLexer;
tokens {
If, Else, While // etc
}
@header {
import java.util.Map;
}
@members {
private Map<String, Integer> keywords;
public NafiLexer(CharStream input, Map<String, Integer> keywords) {
this(input);
this.keywords = keywords;
}
}
WS: [ \n\t\r]+ -> skip;
ID: [a-zA-Z]+ { if(keywords.containsKey(getText())) setType(keywords.get(getText())); };
しかし、私はすべてのターゲット固有を削除したいです私の.g4
ファイルのコードは、私の.g4
が別々のプロジェクトのために複数のターゲット言語にまたがって使用されるためです。
Parser
では、埋め込みアクションを削除するのにListener
を使用して、アプリケーション固有のコードから文法を切り離すことができます。しかし、レクサーレベルでこれを行う方法がある場合、私はまだそれを見つける必要があります(したがって、この質問をしています)。
これを達成する方法は、Lexer
から引き出されたTokenStream
をラップするように思われます。このラップTokenStream
は、提供された通りにToken
を読み込み、現在の埋め込みアクションの変換を、存在するトークンID
に適用します。
これは(理論的には)実装するのが難しくありません。しかし、これはすでに定義されているANTLRシンボルだけで可能な機能性のように感じられます。ですから、問題は:既存のANTLRシステム内でTokenStream
を通過するトークンの種類を条件付きで変更することは可能ですか?そうでない場合は、そのタスクを達成するための最も摩擦の少ない方法は何ですか? Javaライブラリを使用した例が優先されます。これは私が最もよく知っているものです。
サブ質問:必要なターゲットのためにTokenTransformationStream
を作成すると、それを既存のライブラリに追加することをお勧めしますか? (私はすべての現在の供給目標のためのシンボルを作成することができます。)
をはい、これはあなたが定期的にコンストラクタでレクサーを構築した場合にクラッシュします。実際のアプリケーションでは、それを修正する価値があるかもしれませんが、この例では問題ではありません。
これは、いくつかの理由から、これはレクサーレベルにとって適切な作業だと思います。主な理由は、キーワードを常にキーワードトークンとして渡し、必要に応じて、パーサーレベルで識別子として使用できるようにすることです(状況依存キーワードなど)。また、他の質問は単にこの効果を達成する方法は、上記の提供された組み込みアクションのソリューションと基本的に同等の方法を示唆する示唆する。
です.v4.runtime.TokenStreamRewriter'ですが、javadocを正しく読み込んでいる場合は、テキスト表現を変更するためだけです。 – CAD97
字句解析/構文解析が始まる前に、この「実行時設定」を何とか知っていますか? – cantSleepNow
@cantSleepNowはい、それは各実行時の前と定数で知られています。 – CAD97