SQL のコマンド ライン クライアントに単純なオートコンプリートを実装しようとしています。アプリケーションの残りの部分でパーサーを生成するために antlr を使用していますが、文法を再利用してオートコンプリートを使用したいと考えていました。私の考えは次のとおりです: - ユーザーが完了を要求したときに不完全なステートメントを解析します (たとえばselect a from
) - パーサーから、彼が発生したときに予想されたトークンのリストを取得しますNoViableAltException
次に、このトークンのリストから実行したかったのは、次のとおりです。
これは原則として (少なくとも私には) 賢明なアイデアのように見え、私はこれを見つけまし た。
ただし、いくつかのテストを行った後、 「;」のみを含むstate.following[state._fsp]
エントリなど、多くのトークンが含まれていないことに気付きました。create
この部分の文法は次のようになります。
root : statement? (SEMICOLON!)? EOF!;
statement : create | ...;
create : CREATE | ( TABLE table_create | USER user_create | ....);
だから私は混乱して、生成されたコードを見ました:
try {
int alt6=16;
alt6 = dfa6.predict(input);
switch (alt6) {
case 1 :
{
root_0 = (CommonTree)adaptor.nil();
pushFollow(FOLLOW_create_in_statement1088);
create8=create();
state._fsp--;
adaptor.addChild(root_0, create8.getTree());
}
break;
case 2 :
...
それで、それは私には理にかなっています:パーサーは次のトークンを読み取ろうとし、次にこのトークンから次のルールを見つけます(大文字と小文字を切り替えます)。私の場合、次のトークンがないため、予測は失敗します。そこから、antlr を少しハックする必要があることを理解し、テンプレートを調べたJava.stg
ところ、次のコードが見つかりました。
/** A (...) subrule with multiple alternatives */
block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
// <fileName>:<description>
int alt<decisionNumber>=<maxAlt>;
<decls>
<@predecision()>
<decision>
<@postdecision()>
<@prebranch()>
switch (alt<decisionNumber>) {
<alts:{a | <altSwitchCase(i,a)>}>
}
<@postbranch()>
>>
と
/** A case in a switch that jumps to an alternative given the alternative
* number. A DFA predicts the alternative and then a simple switch
* does the jump to the code that actually matches that alternative.
*/
altSwitchCase(altNum,alt) ::= <<
case <altNum> :
<@prealt()>
<alt>
break;<\n>
>>
そこから私がしなければならないと思ったのは、predict の呼び出しの前にすべての altNum をスタックに入れる独自の関数を実行することだけでした。だから私は試してみました: /* Yout }>*/
そして、トークン ID の素敵な小さなリストが得られることを期待していました。しかし、まったく違うものを得るわけではありません。
したがって、私は本当に迷っており、このオートコンプリート機能を手動で実行しなくても簡単に提供できる方法があるかどうか、またはテンプレートを変更してカスタム スタックを追加してさまざまな代替手段を追加する方法が欠けているかどうかを知りたいと思います。例外が発生した後にそれを読むことができるようにするためのルール
どうもありがとうございました