2

私はANTLRを初めて使用し、次を使用してクエリを解析しようとしています。

grammar SearchEngineQuery; 

options { language = CSharp2; output = AST; } 

tokens {
AndNode;
}

LPARENTHESIS : '('; 
RPARENTHESIS : ')'; 

AND    : 'and'; 
OR     : 'or'; 
ANDNOT : 'andnot'; 
NOT    : 'not'; 
NEAR    : 'near'; 


fragment CHARACTER : ('a'..'z'|'0'..'9'|'-'); 
fragment QUOTE     : ('"'); 
fragment WILDCARD  : ('*'|'?'); 
fragment SPACE     : (' '|'\n'|'\r'|'\t'|'\u000C'); 

WILD_STRING 
   : (CHARACTER)* 
     ( 
       ('?') 
       (CHARACTER)* 
     )+ 
   ; 
PREFIX_STRING 
   : (CHARACTER)+
     ( 
       ('*')  
     )+ 
   ; 
WS     : (SPACE) { $channel=HIDDEN; }; 
PHRASE : (QUOTE)(WORD)(WILDCARD)?((SPACE)+(WORD)(WILDCARD)?)*(QUOTE); 
WORD   : (CHARACTER)+; 

startExpression  : nearExpression; 
nearExpression     : andExpression (NEAR^ andExpression)*; 
andExpression 
  :  (andnotExpression        ->  andnotExpression) 
     (AND? a=andnotExpression -> ^(AndNode $andnotExpression $a))*  
  ; 

andnotExpression : orExpression (ANDNOT^ orExpression)*; 
orExpression     : notExpression (OR^ notExpression)* ; 
notExpression    : (NOT^)? (phraseExpression | wildExpression | prefixExpression | atomicExpression); 
phraseExpression : (PHRASE^);
wildExpression    : (WILD_STRING^); 
prefixExpression    : (PREFIX_STRING^); 
atomicExpression :  WORD | LPARENTHESIS! andExpression RPARENTHESIS!; 

これは、一般的なクエリでは問題なく機能するようです。ただし、の場合はa near (b or c)実際には次のように処理する必要があります。

代替テキスト

a near (b or c and (d or e))次のように処理する必要があります。

代替テキスト

私はこれを行う方法を決定することができません。どんな助けでも大歓迎です。

ありがとう

4

1 に答える 1

0

おそらく、複数パス ツリー書き換え文法を使用することで、これを達成できるでしょう。ルールはかなり短くする必要があります。

OR の場合は次のようになります。

orCaseRight: a=. NEAR ^(OR x=. y=.) -> ^(OR ^(NEAR $a $x) ^(NEAR $a $y));
orCaseLeft: ^(OR x=. y=.) NEAR a=. -> ^(OR ^(NEAR $a $x) ^(NEAR $a $y)); 

topDown に、ルールが一致するたびにフラグを設定するアクションを追加しrewriteて、フラグが設定されている限りこの文法を適用できるようにしますrewrite

これを使用して数式を最適化/事前計算すると、魅力的に機能します。

于 2012-01-19T20:40:44.947 に答える