ANTLR переписать текст запроса, чтобы повторить текст с более ранними узлами - PullRequest
2 голосов
/ 19 ноября 2010

Я новичок в 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) должен быть обработан как:

alt text

, а a near (b or c and (d or e)) должен быть обработан как:

alt text

Я не могу определить, как это сделать.Любая помощь будет наиболее ценной.

Спасибо

1 Ответ

0 голосов
/ 20 января 2012

Вы, вероятно, сможете достичь этого, используя грамматику многократного переписывания дерева проходов.Правила должны быть довольно короткими.

примерно так же, как это для случая ИЛИ:

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.

Я использую это для оптимизации / предварительного вычисления математических выражений, и это работает как шарм.

...