我想创建一个ANTLR calculator example的交互式版本,告诉用户下一步要键入什么。例如,在开始时,ID
,INT
,NEWLINE
和WS
令牌是可能的。忽略WS
,建议消息可能是:
Type an identifier, a number, or newline.
解析数字后,该消息应为
Type +, -, *, or newline.
等等。怎么做?
修改
到目前为止我尝试过:
private void accept(String sentence) {
ANTLRInputStream is = new ANTLRInputStream(sentence);
OperationLexer l = new OperationLexer(is);
CommonTokenStream cts = new CommonTokenStream(l);
final OperationParser parser = new OperationParser(cts);
parser.addParseListener(new OperationBaseListener() {
@Override
public void enterEveryRule(ParserRuleContext ctx) {
ATNState state = parser.getATN().states.get(parser.getState());
System.out.print("RULE " + parser.ruleNames[state.ruleIndex] + " ");
IntervalSet following = parser.getATN().nextTokens(state, ctx);
for (Integer token : following.toList()) {
System.out.print(parser.tokenNames[token] + " ");
}
System.out.println();
}
});
parser.prog();
}
为第一个令牌打印正确的建议,但对于所有其他令牌,它会打印当前令牌。我想在enterEveryRule()
捕捉状态太早了。
答案 0 :(得分:1)
在LL(k)解析器中准确收集此信息,其中k> 1,需要彻底了解解析器内部。几年前,我遇到了ANTLR 3的这个问题,发现唯一真正的解决方案是如此复杂,导致我成为ANTLR 4 的特别的共同作者,所以我可以处理这个问题。 / p>
ANTLR(包括ANTLR 4)在解析阶段消除解析树的歧义,这意味着如果您的语法不是LL(1),那么在解析树中执行此分析意味着您已经丢失了准确所需的信息。您需要编写自己的ParserATNSimulator
版本(或包装它的自定义解释器),它不会丢失信息。