ANTLR - 树中的隐式AND标记

时间:2010-08-02 22:44:47

标签: antlr antlr3

我正在尝试构建一个解释用户输入文本,搜索引擎样式的语法。它将支持AND,OR,NOT和ANDNOT布尔运算符。我几乎所有工作都有效,但是我想添加一个规则,即在带引号的字符串之外的两个相邻关键字被隐含地视为AND子句。例如:

奶酪和饼干=奶酪和饼干

(上下)或(左右)=(上下)或(左右)

猫狗“大肚猪”=猫与狗和“大肚猪”

我遇到了最后一个问题,我希望有人可以指出我正确的方向。到目前为止,这是我的* .g文件,请保持良好,我的ANTLR体验不到一个工作日:

grammar SearchEngine;

options { language = CSharp2; output = AST; }

@lexer::namespace { Demo.SearchEngine }
@parser::namespace { Demo.SearchEngine }

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

AND    : ('A'|'a')('N'|'n')('D'|'d');
OR     : ('O'|'o')('R'|'r');
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t');
NOT    : ('N'|'n')('O'|'o')('T'|'t');

fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9');
fragment QUOTE     : ('"');
fragment SPACE     : (' '|'\n'|'\r'|'\t'|'\u000C');

WS     : (SPACE) { $channel=HIDDEN; };
PHRASE : (QUOTE)(CHARACTER)+((SPACE)+(CHARACTER)+)+(QUOTE);
WORD   : (CHARACTER)+;

startExpression  : andExpression;
andExpression    : andnotExpression (AND^ andnotExpression)*;
andnotExpression : orExpression (ANDNOT^ orExpression)*;
orExpression     : notExpression (OR^ notExpression)*;
notExpression    : (NOT^)? atomicExpression;
atomicExpression : PHRASE | WORD | LPARENTHESIS! andExpression RPARENTHESIS!;

1 个答案:

答案 0 :(得分:6)

由于你的AND规则有可选的AND-keyword,你应该创建一个虚构的AND-token并使用重写规则在树中“注入”该标记。在这种情况下,您无法使用ANTLR的简写^根运算符。您必须使用->重写运算符。

您的andExpression应如下:

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

The Definitive ANTLR Reference的第7章, 在子规则中重写规则 ,第173-174页中的 重写规则 一节中详细说明了这一点(可能是含糊不清的)特伦斯帕尔。

我运行了一个快速测试,看看语法是否使用新的andExpression规则生成了正确的AST。解析字符串cat dog "potbelly and pig" and FOO后,生成的解析器生成以下AST:

alt text http://img580.imageshack.us/img580/7370/andtree.png

请注意,AndNodeRootimaginary tokens

如果您想知道如何创建上面的AST图片,请参阅此主题:Visualizing an AST created with ANTLR (in a .Net environment)

修改

解析one two three(one two) three时,会创建以下AST:

alt text http://img203.imageshack.us/img203/2558/69551879.png

解析(one two) OR three时,会创建以下AST:

alt text http://img340.imageshack.us/img340/8779/73390353.png

在所有情况下似乎都是正确的方式。