1

私はレクサーとパーサーの初心者なので、しばらくお待ちください。最終的には、'(foo=bar)'、'(!foo=bar)'、'(&(foo=bar)(!zip=zap))' などの LDAP スタイルのクエリ文字列を表現できるようにしたいと考えています。最後に、実際のデータベースクエリ(または何でも)を作成するために使用できるツリー

そこで、(foo=bar) や (!foo=bar) のような式を解析するための最も単純な形式から始めようと考えましたが、すでにいくつかの理解の問題があります。フィールドが「=」によって値と区切られていることを表現したいだけですが、識別子が値によく似ているため、ANTLR は一度にすべての文字を食べているようです。これを防ぐにはどうすればよいですか?

grammar FilterExpression;

options
{
    language=Java;
    k=2;
}

tokens
{
    NOT='!';
}

term    :   '(' NOT? FIELD '=' VALUE ')';
// lexer
FIELD   :   NAME;
VALUE   :   CDATA;

fragment NAME
    :   ALPHA+;
fragment CDATA
    :   ALPHA*;
fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');
4

2 に答える 2

2

さて、あなたはここで正しい軌道に乗っています。変更する必要があるのはほんの一部です。レクサーではフィールド名とフィールド値を区別する方法がないため、レクサーではなくパーサーでフィールド名フィールド値を表現する必要があります。同じフラグメントを使用する複数のレクサー式があると、レクサーがこれらのどれを必要としているかを判断するのが非常に難しくなります (不可能です!)。これら 2 つ (名前と値) の決定をパーサーに移すと、非常に簡単になります。をオプションにするには、そのパーサー用語をオプションにします (後ろに「?」を付けます)。変更された文法で生成された構文木については、以下を参照してください (これがあなたの求めていたものであることを願っています)。また、回答の下部に修正した文法を貼り付けました。
代替テキスト http://img268.imageshack.us/img268/7374/graphw.png

grammar FilterExpression;

options
{
    language=Java;
    k=2;
}

tokens
{
    NOT='!';
}

term    :       '(' NOT? field '=' value? ')';
// lexer
field   :       ID;
value   :       ID;

ID  :   ALPHA+
    ;

fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');
于 2009-07-30T06:18:11.427 に答える
0

フィールドと値が両方とも識別子であり、識別子が空でないアルファベット文字列である場合(例のように値を空にすることができます)、次のようにすることができます。

term    :       '(' NOT? field '=' value ')';

field : IDENTIFIER ;

value : IDENTIFIER? ;

// lexer
IDENTIFIER : ALPHA+ ;

fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');

レクサーは値からフィールドを判断できないため、レクサーにそれらを同じように扱わせ、パーサーを使用してコンテキストに基づいて違いを判断する必要があります。

于 2009-06-26T14:43:45.340 に答える