使用antlr3创建语法来解析搜索引擎,如语法,这是我需要帮助的任务。
语法应该允许:
实施上述所有标准是一项挑战(对我而言)。请查看我的语法,建议错误和修复,因为无法正确满足所有标准。
语法
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。
答案 0 :(得分:1)
首先去ANTLR,你做的不仅仅是一份好工作。
'('
令牌中')'
和WORD
的事实是因为范围'\u0021'..'\u0039'
包含括号。 ANTLR的词法分析器匹配贪婪的字符,和尝试尽可能匹配(!)。由于最后一条规则(匹配尽可能多的字符),它将从输入中创建单个标记,如"(bird"
(WORD
标记),不两个标记(一个LPARENTHESIS
和一个WORD
)。只需确保括号不包含在WORD
需要匹配的内容中。
如果我复制你的语法并将WORD
更改为:
WORD : CHARACTER+;
您的输入被解析为:
是否可以将括号作为术语的正常部分?例如blabla(bla(a)blabla被认为是2个单词?解析器必须决定括号是否引入一个子项,或者只是形成WORD的普通字符。
你可以 lexer-level> 这样做,假设(a...
和...a)
中的括号是表达式的一部分,不属于WORD
:
WORD : UNICODENOSPACES ((UNICODENOSPACES | '(' | ')')* UNICODENOSPACES)?
现在只允许WORD
内的括号。您可以通过允许(
结尾的WORD
也有效,但我不确定这是不是一个好主意。