ANTLR重写查询文本以与早期节点重复文本

ANTLR重写查询文本以与早期节点重复文本,antlr,antlr3,antlrworks,Antlr,Antlr3,Antlrworks,我是ANTLR新手,正在尝试使用以下方法解析查询 grammar SearchEngineQuery; options { language = CSharp2; output = AST; } tokens { AndNode; } LPARENTHESIS : '('; RPARENTHESIS : ')'; AND : 'and'; OR : 'or'; ANDNOT : 'andnot'; NOT : 'not'; NEAR : 'nea

我是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靠近b或c的情况需要实际处理为:

a靠近b或c和d或e需要处理为:

我无法确定如何做到这一点。任何帮助都将不胜感激


谢谢

您可能可以通过使用多重传递树重写语法来实现这一点。 规则应该相当简短

与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)); 
在自上而下中,每当规则匹配时,添加设置重写标志的操作,以便只要设置了重写标志,就可以应用此语法


我使用它来优化/预计算数学表达式,它的工作方式很有魅力。

您可能可以通过使用多重传递树重写语法来实现这一点。 规则应该相当简短

与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)); 
在自上而下中,每当规则匹配时,添加设置重写标志的操作,以便只要设置了重写标志,就可以应用此语法


我用它来优化/预计算数学表达式,它就像一个魔咒。

a和b或c呢?这也应该转化为a和b还是a和c?a靠近b或c和d或e?a和b或c可以按原样处理。这是需要通过分解查询来处理的near选项。对于接近b或c和d或e的a,理想情况下也应该分解。很抱歉延迟回复。我是stackexchange新手,只是一直在我的个人资料中查看这个问题的答案值。现在我知道了。还有一件事,你的语法允许a接近x接近b或c,对吗?如果是这样,那应该产生什么样的AST?@Bart,靠近b或c的近x应该被解析为靠近b或c的近x=>靠近c的近x或接近c的近x。我知道事情会变得很复杂。我想我需要检查查询的复杂性,然后决定是否允许处理该查询,或者停止代码的执行,并要求修改查询input@Puneet嗯,我明白了。有相当多的AST重新订购正在进行。我不认为这可以在语法本身,无论是在组合语法还是从树语法,但我可能是错误的,当然。。。我会仔细考虑一下,但是现在,我要说的是,在创建AST之后,您必须自己手动重新排序AST。请参阅CommonTree的API,以了解如何获得子类以及所述类的其他属性。祝你好运。a和b或c呢?这也应该转化为a和b还是a和c?a靠近b或c和d或e?a和b或c可以按原样处理。这是需要通过分解查询来处理的near选项。对于接近b或c和d或e的a,理想情况下也应该分解。很抱歉延迟回复。我是stackexchange新手,只是一直在我的个人资料中查看这个问题的答案值。现在我知道了。还有一件事,你的语法允许a接近x接近b或c,对吗?如果是这样,那应该产生什么样的AST?@Bart,靠近b或c的近x应该被解析为靠近b或c的近x=>靠近c的近x或接近c的近x。我知道事情会变得很复杂。我想我需要检查查询的复杂性,然后决定是否允许处理该查询,或者停止代码的执行,并要求修改查询input@Puneet嗯,我明白了。有相当多的AST重新订购正在进行。我不认为这可以在语法本身,无论是在组合语法还是从树语法,但我可能是错误的,当然。。。我会仔细考虑一下,但是现在,我要说的是,在创建AST之后,您必须自己手动重新排序AST。请参阅CommonTree的API,以了解如何获得子类以及所述类的其他属性。祝你好运。对不起,我怎么循环语法呢?您能进一步解释一下吗?这将在解析器调用代码中执行。在我看来,它看起来像这样:简化表达式,而不是真的{CommonTreeNodeDestream节点=新建CommonTreeNodeDestreamDownUp;表达式简化表达式简化=新建表达式简化节点;downup=树表达式简化。downupdownup,false;if!表达式简化。重写是否中断;}很抱歉,代码混乱,注释中不支持return。基本上,只要重写器仍在重写某些内容,我就用上一步的结果调用TreeRewriter。很抱歉,但我将如何循环语法?你能进一步解释吗?这将在解析器调用代码中执行。在我的示例中,它类似于这://简化表达式,而true{commonTreeNodesTeam nodes=new CommonTreeNodesStreamDownup;表达式简化表达式简化=
新表达式简化节点;downup=树表达式Simplifying.downup,false;如果expressionSimplifying.u重写中断;}很抱歉代码混乱,注释中不支持return。基本上,只要重写器仍然重写某些内容,我就用上一遍的结果调用TreeRewriter。