java - ANTLR4 是否可以确定适用于某些位置的代币类型?

标签 java antlr antlr4

我正在尝试在 ANTLR4 之上构建某种自动完成工具,但我遇到了问题(可能与我的理解有关)。我正在使用 ErrorListener 并尝试从 RecognitionException 对象获取适用的标记,但这种方法并不总是有效。

我有一个语法:

grammar WhereClause;

USER_NAME_COLUMN: 'user_name' ;
USER_AGE_COLUMN: 'user_age';
EQ : '=' ;
LTH : '<' ;
GTH : '>' ;
WS : ( ' ' | '\t' )+ -> skip ;


stringColumn: USER_NAME_COLUMN ;
numericColumn: USER_AGE_COLUMN;
stringRelationalOperator: EQ ;
numericRelationalOperator: EQ | LTH | GTH ;
expression: stringColumn stringRelationalOperator stringColumn | numericColumn numericRelationalOperator numericColumn ;

以及某种简单的测试:

public static void main(String... args) {
    String data = "user_name = user_name";
    for (int i = 1; i <= data.length(); i++) {
        String input = data.substring(0, i);
        System.out.println("===========================");
        System.out.println(">> " + input + "");
        parse(input);
    }
}

private static void parse(String input) {
    ANTLRInputStream inputStream = new ANTLRInputStream(input);
    WhereClauseLexer lexer = new WhereClauseLexer(inputStream);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    WhereClauseParser parser = new WhereClauseParser(tokens);
    lexer.removeErrorListeners();
    parser.removeErrorListeners();
    parser.addErrorListener(new ANTLRErrorListener() {
        @Override
        public void syntaxError(Recognizer<?, ?> recognizer, Object o, int i, int i1, String s, RecognitionException e) {
            Vocabulary vocabulary = recognizer.getVocabulary();
            if (e != null) {
                e.getExpectedTokens().getIntervals().forEach(interval -> {
                    for (int j = interval.a; j <= interval.b; j++) {
                        System.out.println(vocabulary.getDisplayName(j));
                    }
                });
            }
        }

        @Override
        public void reportAmbiguity(Parser parser, DFA dfa, int i, int i1, boolean b, BitSet bitSet, ATNConfigSet atnConfigSet) {}
        @Override
        public void reportAttemptingFullContext(Parser parser, DFA dfa, int i, int i1, BitSet bitSet, ATNConfigSet atnConfigSet) {}
        @Override
        public void reportContextSensitivity(Parser parser, DFA dfa, int i, int i1, int i2, ATNConfigSet atnConfigSet) {}
    });
    parser.expression();
}

结果我得到以下输出:

===========================
>> u
'user_name'
'user_age'
===========================
>> us
'user_name'
'user_age'
===========================
>> use
'user_name'
'user_age'
===========================
>> user
'user_name'
'user_age'
===========================
>> user_
'user_name'
'user_age'
===========================
>> user_n
'user_name'
'user_age'
===========================
>> user_na
'user_name'
'user_age'
===========================
>> user_nam
'user_name'
'user_age'
===========================
>> user_name
'='
===========================
>> user_name 
'='
===========================
>> user_name =
===========================
>> user_name = 
===========================
>> user_name = u
===========================
>> user_name = us
===========================
>> user_name = use
===========================
>> user_name = user
===========================
>> user_name = user_
===========================
>> user_name = user_n
===========================
>> user_name = user_na
===========================
>> user_name = user_nam
===========================
>> user_name = user_name

这意味着我没有获得平等正确部分的预期标记。有人知道原因吗?是否有可能知道哪个标记(标记)应该跟随输入行?

最佳答案

使用错误位置来完成代码效果不佳。如果插入符号位置和错误位置不一致怎么办?此外,这种简单的方法只会为您提供预期的关键字标记,但通常您需要更多(例如给定位置的所有可用变量)。因此,您需要一个符号表,需要一种方法来确定给定位置所需的符号类型等。

使用解析器来获取代码完成候选者效果不佳。请记住,解析器访问与输入匹配的单个路径,但您需要所有可能的路径。

this blog post我描述了一种使用 ANTLR3 的可能方法,并且我正在为 ANTLR4 开发一种方法。另一种尝试由 Federico Tomassetti 发布。它仍然只返回关键字,但至少它不使用解析器。

这里是 Terence Parr 关于提供一个返回所有跟随集的函数的讨论:https://github.com/antlr/antlr4/issues/1428

关于java - ANTLR4 是否可以确定适用于某些位置的代币类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41782886/

相关文章:

antlr - 如何捕捉小错误?

c# - 基于ANTLR4语法实现语言自动补全

ANTLR4:获取每个规则的开始和结束索引:$stop 行为奇怪

java - JBoss JAAS 自定义登录模块错误消息

java - Antlr3 解析不完整语句时的下一个可用标记

java - c# 解压缩错误 使用不支持的压缩方法压缩存档条目

java - ANTLR - 如何确定什么样的解析树 "best fits"一些代码

java - RuleContext 类实现中的 invokingState 是什么?

java - Java中高效的方法参数

Java - Oracle - XML 时区