1

创建一个语法来解析像 antlr3 这样的搜索引擎是我需要帮助的任务。

语法应该允许:

  • 在术语之间省略 AND:示例 dog cat = dog AND cat
  • AND 应该优先于 OR:cat dog or boat = (cat AND dog) or boat
  • 括号中术语的任意封装:cat OR( dog and (fish cow) OR bird)

实施上述所有标准是一个挑战(对我来说)。请查看我的语法建议错误和修复,因为无法满足所有标准。

语法

tokens {
FOR;
END;
FIELDSEARCH;
TARGETFIELD;
RELATION;
ANDNODE;
}
startExpression  : orEx;

expressionLevel4    
: LPARENTHESIS! orEx RPARENTHESIS! | atomicExpression;

expressionLevel3    
: (fieldExpression) | expressionLevel4 ;

expressionLevel2    
: (nearExpression) | expressionLevel3 ;

expressionLevel1    
: (countExpression) | expressionLevel2 ;

notEx   : (NOT^)? expressionLevel1;

andEx   : (notEx        -> notEx)
(AND? a=notEx -> ^(ANDNODE $andEx $a))*;

orEx    : andEx (OR^  andEx)*;

countExpression  : COUNT LPARENTHESIS WORD RPARENTHESIS (LESSTHEN|MORETHEN) EQUAL? NUMBERS -> ^(COUNT WORD ^(RELATION LESSTHEN? MORETHEN? EQUAL?) NUMBERS);

nearExpression  : NEAR^ LPARENTHESIS! (WORD|PHRASE) MULTIPLESEPERATOR! (WORD|PHRASE) MULTIPLESEPERATOR! NUMBERS RPARENTHESIS!;

fieldExpression : WORD PROPERTYSEPERATOR WORD -> ^(FIELDSEARCH ^(TARGETFIELD WORD));

atomicExpression 
: WORD
| PHRASE ;


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

LESSTHEN : '<';
MORETHEN : '>';
EQUAL : '=';

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');
COUNT:('C'|'c')('O'|'o')('U'|'u')('N'|'n')('T'|'t');
NEAR:('N'|'n')('E'|'e')('A'|'a')('R'|'r');
PROPERTYSEPERATOR : ':';
MULTIPLESEPERATOR : ',';

fragment NUMBER : ('0'..'9');
fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'?');
fragment QUOTE     : ('"');

fragment SPACE     : ('\u0009'|'\u0020'|'\u000C'|'\u00A0');

//fragment UNICODENOSPACES  :  ('\u0000'..'\u0008'|'\u0010'..'\u0019'|'\u0021'..'\009F'|'\u00A1'..'\009F');
fragment UNICODENOSPACES  :  ('\u0021'..'\u0039'|'\u003B'..'\u007E'|'\u00A1'..'\uFFFF');

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

给定输入:

title:cats AND  fish OR Bird AND (bird and dirt) OR (bart or title:bard OR bird AND title:dort)

此 AST 已创建,请注意在 WORD 术语中捕获的 ( )。 在此处输入图像描述

可能还有其他错误或愚蠢的实现细节。这是我第一次使用 antlr。

4

1 回答 1

1

对于 ANTLR 的第一次尝试,您所做的不仅仅是一份出色的工作。

你的标记中有'('and的事实是因为范围包含括号。ANTLR 的词法分析器贪婪地匹配字符,尝试尽可能多地匹配(!)。由于最后一条规则(匹配尽可能多的字符),它将根据输入(例如(a标记))创建单个标记,而不是两个标记(a和 a )。只要确保括号不包含在任何需要匹配的内容中。')'WORD'\u0021'..'\u0039'"(bird"WORDLPARENTHESISWORDWORD

如果我复制您的语法并更改WORD为:

WORD : CHARACTER+;

您的输入被解析为:

在此处输入图像描述

编辑

是否可以将括号作为术语的正常部分?例如,blabla(bla(a)blabla 是否被识别为 2 个 WORDS?解析器必须决定括号是否引入了子项,或者只是形成 WORD 的普通字符。

可以在lexer-level上这样做,假设(a...and中的括号...a)是表达式的一部分,而不是 a 的一部分WORD

WORD : UNICODENOSPACES ((UNICODENOSPACES | '(' | ')')* UNICODENOSPACES)?

现在只允许在 a 中使用括号WORD。您可以通过允许 a(结尾的 aWORD也更有效,但我不确定这是否是一个好主意。

于 2012-11-28T18:42:26.090 回答