如何创建动态ANTLR4词法分析器

时间:2017-12-04 16:52:58

标签: java antlr4

我有下一个语法

grammar SearchEngine;

@lexer::members {
  private java.util.Set<String> extraCriteria;

  public SearchEngineLexer(CharStream input, java.util.Set<String> extraCriteria) {
    this(input);
    this.extraCriteria = extraCriteria;
  }
}

query: expression EOF;

expression: criteria operator literal_value | expression 'AND' expression | expression 'OR' expression;

criteria : 'SERVICE_NAME' | ..a lot of hardcoded criterias here | EXTRA_CRITERIA;

EXTRA_CRITERIA: {extraCriteria.stream().filter(c -> c.equals(getText())).findFirst().isPresent()}? . ;

它接受诸如SERVICE_NAME ='something'或EXCEPTION IS NULL之类的查询,依此类推。我的语法的其余部分并不重要,因为它没有EXTRA_CRITERIA定义。

所以,我创建了新的词法分析器,其中“TestCriteria”作为额外标准并试图解析我的查询:

Lexer lexer = new SearchEngineLexer(CharStreams.fromString("TestCriteria != 'test' OR SERVICE_NAME = 'EchoService'"), Collections.singleton("TestCriteria"));
TokenStream tokenStream = new CommonTokenStream(lexer);
SearchEngineParser parser = new SearchEngineParser(tokenStream);
parser.setErrorHandler(new BailErrorStrategy());
SearchEngineParser.QueryContext context = parser.query();

但是当我执行这段代码时,我会检索

line 1:0 token recognition error at: 'Te'
line 1:2 token recognition error at: 'st'
line 1:4 token recognition error at: 'C'
line 1:5 token recognition error at: 'ri'
line 1:7 token recognition error at: 'te'
line 1:9 token recognition error at: 'ri'
line 1:11 token recognition error at: 'a'
org.antlr.v4.runtime.misc.ParseCancellationException
    at org.antlr.v4.runtime.BailErrorStrategy.recoverInline(BailErrorStrategy.java:66)
    at de.telekom.tvpp.mtool.language.SearchEngineParser.criteria(SearchEngineParser.java:277)
    at de.telekom.tvpp.mtool.language.SearchEngineParser.expression(SearchEngineParser.java:180)
    at de.telekom.tvpp.mtool.language.SearchEngineParser.query(SearchEngineParser.java:117)
    at de.telekom.tvpp.mtool.language.App.main(App.java:22)
Caused by: org.antlr.v4.runtime.InputMismatchException
    at org.antlr.v4.runtime.BailErrorStrategy.recoverInline(BailErrorStrategy.java:61)
    ... 4 more

我哪里错了?如何设置ANTL4使用动态规则?

1 个答案:

答案 0 :(得分:0)

我在表达中犯了一个错误。这是我的解决方案:

grammar SearchEngine;


@lexer::members {
  private java.util.Set<String> extraCriteria;

  public SearchEngineLexer(CharStream input, java.util.Set<String> extraCriteria) {
    this(input);
    this.extraCriteria = extraCriteria;
  }

  private boolean isExtraCriteria() {
      return extraCriteria.stream().anyMatch(term -> ahead(term, _input));
  }

  private boolean ahead(final String word, final CharStream input) {
      for (int i = 0; i < word.length(); i++) {
          char wordChar = word.charAt(i);
          int inputChar = input.LA(i + 1);

          if (inputChar != wordChar) {
              return false;
          }
      }

      input.seek(input.index() + word.length() - 1);

      return true;
  }
}

query: expression EOF;

expression: criteria operator literal_value | expression 'AND' expression | expression 'OR' expression;

criteria : 'SERVICE_NAME' | ..a lot of hardcoded criterias here | EXTRA_CRITERIA;

EXTRA_CRITERIA: {isExtraCriteria()}? . ;