Antlr语法混乱。给出明确错误时不报告错误

问题描述 投票:0回答:1

我试图设计一个简单的查询语言,如下所示

grammar FilterExpression;


// Lexer rules

AND : 'AND' ;
OR  : 'OR' ;
NOT : 'NOT';

GT : '>' ;
GE : '>=' ;
LT : '<' ;
LE : '<=' ;
EQ : '=' ;

DECIMAL    : '-'?[0-9]+('.'[0-9]+)? ;
KEY       : ~[ \t\r\n\\"~=<>:(),]+ ;
QUOTED_WORD: ["] ('\\"' | ~["])* ["] ;
NEWLINE    : '\r'? '\n';
WS         : [ \t\r\n]+ -> skip ;



StringFilter   : KEY ':' QUOTED_WORD;
NumericalFilter  : KEY (GT | GE | LT | LE | EQ) DECIMAL;

condition      : StringFilter                                # stringCondition
               | NumericalFilter                             # numericalCondition
               | StringFilter op=(AND|OR) StringFilter       # combinedStringCondition
               | NumericalFilter op=(AND|OR) NumericalFilter # combinedNumericalCondition
               | condition AND condition                     # combinedCondition
               | '(' condition ')'                           # parens
               ;

我添加了一些测试,想验证一下它们是否如预期的那样工作。令我惊讶的是,一些明显应该是错误的情况下,通过了

例如,当我输入

(brand:"apple" AND t>3) 1>3

其中 1>3 故意放成错误。然而,Antlr似乎仍在愉快地生成一棵看起来像树的树。enter image description here

是不是因为我的语法有一些我没有意识到的问题?

我也在IntelliJ插件中试了一下(因为我觉得grun可能没有达到预期的效果),但它给出的结果是

我正在使用的测试代码。注意,我还尝试使用BailErrorStrategy,但这些似乎没有帮助

public class ParserTest {
  private class BailLexer extends FilterExpressionLexer {
    public BailLexer(CharStream input) {
      super(input);
    }
    public void recover(LexerNoViableAltException e) {
      throw new RuntimeException(e);
    }
  }


  private FilterExpressionParser createParser(String filterString) {
    //FilterExpressionLexer lexer = new FilterExpressionLexer(CharStreams.fromString(filterString));
    FilterExpressionLexer lexer = new BailLexer(CharStreams.fromString(filterString));
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    FilterExpressionParser parser = new FilterExpressionParser(tokens);

    parser.setErrorHandler(new BailErrorStrategy());
    parser.addErrorListener(new ANTLRErrorListener() {
      @Override
      public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        System.out.print("here1");
      }

      @Override
      public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) {
        System.out.print("here2");

      }

      @Override
      public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) {
        System.out.print("here3");

      }

      @Override
      public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) {

        System.out.print("here4");
      }
    });

    return parser;
  }

  @Test
  public void test() {
    FilterExpressionParser parser = createParser("(brand:\"apple\" AND t>3) 1>3");
    parser.condition();
  }

}
java antlr antlr4 antlrworks
1个回答
1
投票

看来我终于找到了答案。

原因是在语法中我没有提供EOF。很明显,在ANTLR中,解析前缀os语法是完全没有问题的,这就是为什么测试字符串的其余部分是

(brand:"apple" AND t>3) 1>3 即。1>3 是允许的。

参见这里的讨论。https:/github.comantlrantlr4issues351。

然后,我稍微修改了一下语法,在语法末尾增加了一个EOF的内容 condition EOF 万事如意

© www.soinside.com 2019 - 2024. All rights reserved.