ANTLR4逻辑表达式



我是ANTLR的新手,正在尝试支持逻辑表达式。我的问题是,语法甚至将单个'&'视为逻辑与(与|和OR相同),情况不应该是这样的。

这是我的语法文件(TagQuery.g4):


query
: (expression)+
;
expression
: keyValue                                                #comparisonExpression
| inExpression                                            #singleInExpression
| hasExpression                                           #singleHasExpression
| expressionGroup                                         #singleExpressionGroup
| expression logicalOperator expression                   #logicalExpression
| expressionGroup logicalOperator expressionGroup         #expressionGroupExpression
;
inExpression
: key IN literalList
;
hasExpression
: HAS key
;
expressionGroup
: NOT? L_RND_BRACKET (expression)+ R_RND_BRACKET
;

keyValue
: key comparisonOperator literal
;
key
:  KEY_PREFIX (keyName) R_RND_BRACKET
;
keyName
: IDENTIFIER
;

comparisonOperator
: EQ | NEQ
;
logicalOperator
: AND | OR
;
literalList
: L_SQ_BRACKET literal (COMMA literal)* R_SQ_BRACKET
;
literal
: STRING_LITERAL
;

// keywords
AND                 : ' '*('&&' | 'AND' | 'and')' '*;
OR                  :  ' '*('||' | 'OR' | 'or')' '*;
IDENTIFIER          : [A-Za-z0-9_]+ ;
ESCAPED_IDENTIFIER  : '"' ( '"' '"' | [^"] )* '"';
STRING_LITERAL      : ''' [A-Za-z0-9_ ]* ''';
NOT                 : ' '*('!' | 'not' | 'NOT')' '*;
HAS                 : ' '*('HAS' | 'has')' '*;
IN                  : ' '*('IN' | 'in')' '*;
EQ                  : ' '*'='' '*;
NEQ                 : ' '*'!='' '*;
L_SQ_BRACKET        : ' '*'['' '*;
R_SQ_BRACKET        : ' '*']'' '*;
L_RND_BRACKET       : ' '*'('' '*;
R_RND_BRACKET       : ' '*')'' '*;
COMMA               : ' '*','' '*;
KEY_PREFIX          : 'tags('' '*;
//KEY_SUFFIX          : ')'' '*;
SPACE               : [ trn]+    -> channel(HIDDEN);
WS                  : [ trn]+    -> channel(HIDDEN);
//BLANK               : ' '*;

一个有效的查询示例如下:tags(environment) = 'prod' && tags(region) = 'syd'

下面是计算查询的方法:

public static Filter forQuery(String query) throws ParseException {
try {
LOGGER.info("Attempting to get tag filter for query {}", query);
CharStream in = CharStreams.fromStream(new ByteArrayInputStream(query.getBytes()));
TagQueryLexer lexer = new TagQueryLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TagQueryParser parser = new TagQueryParser(tokens);
TagQueryListener listener = new TagQueryListener();
parser.addParseListener(listener);
TagQueryParseErrorListener errorListener = new TagQueryParseErrorListener();
parser.addErrorListener(errorListener);
parser.query();
if (errorListener.getException() != null) {
listener.getFilter().setParseError(errorListener.getException());
LOGGER.error("Tag filter for query {} returned an error. Please check query syntax n {}", query, errorListener.getException());
throw errorListener.getException();
}
LOGGER.info("Tag filter for query {} returned successfully", query);
return listener.getFilter();
} catch (IOException e) {
LOGGER.error("Unexpected error encountered while getting filter for query {} n {}", query, e);
throw new RuntimeException(e);
}
}

下面是一些无效的查询:

(tags(project) = 'cloudcollectors' & tags(jira) = 'XTNXBL')
(tags(project) = 'cloudcollectors' | tags(jira) = 'XTNXBL')
(tags(project) = 'cloudcollectors'  tags(jira) = 'XTNXBL')
(tags(project) = 'cloudcollectors' tags(jira) = 'XTNXBL')
(tags(project) = 'cloudcollectors'tags(jira) = 'XTNXBL')

我希望errorListener在上面的方法抛出一个异常,因为这些查询语法不正确。然而,这并没有发生,它们继续返回一个Filter对象。

谁能建议一下如何通过这个?我是不是在语法上遗漏了什么?谢谢你!

正如@kaby76指出的那样,您将得到一个令牌识别错误,这来自Lexer。您还需要将ErrorListener附加到Lexer。

lexer.addErrorListener(errorListener);

另外,您确实希望ErrorListener收集它遇到的所有错误。只是询问errorListener.getException()(可能)只是要给你它遇到的最后一个错误。

当ANTLR遇到syntaxError时,它将在所有附加的侦听器上启用syntaxError(...)方法并继续处理。您可以决定如何对报告给侦听器的语法错误作出反应。

你可以选择如何处理你的异常,但是"normal"过程将是建立一个ArrayList的所有错误,你遇到并使其在TagQueryListener类访问。然后你可以添加方法来检查错误,检查最大严重程度,检查错误计数等(你也可以选择在遇到第一个错误时抛出一个Exception来中止处理,但这不会是一个很好的用户体验。)

(我同意他的建议re:空白处理)

相关内容

  • 没有找到相关文章

最新更新