我正在尝试将代码完成功能添加到文本编辑器中。我认为我可以从Antlr获得非语义内容辅助建议。
在这一点上,我有几个ParserRuleContext。我想访问任何类型的ParserRuleContext的所有终端节点。
例如,我有类似bnf的下面;
class
'class' name = IDENTIFIER '{'
attribute*
'}'
;
attribute
( qualifier += 'public'
| qualifier += 'protected'
| qualifier += 'private')?
(qualifier += 'static')?
(qualifier += 'final')?
'attribute' name = IDENTIFIER ':' type = IDENTIFIER
('(' qualifier += 'unique' ')')?
;
IDENTIFIER : LETTER (LETTER|DIGIT)*;
LETTER : [a-zA-Z];
DIGIT : [0-9];
我在编辑器上写了一句话:
class CLAZZ {
public attribute SOMETHING : String;
}
当用户将光标移动到下面的索引并希望获得内容帮助时:
"public [cursor] attribute SOMETHING : String;
">
内容辅助应获得"最终"one_answers"静态"限定符作为建议。
我用Antlr语法分析器来解析这个句子。然后我通过使用Visitor发现光标位于ClassContext->AttributeContext中。
在visitAttributeContext方法中,我想获得AttributeContext的所有终端,如[public,protected,private,static,final,unique]。然后,我将根据光标位置消除除"static,final"之外的其他限定符。
最后,我的问题是,如何从任何ParserRuleContex中获取所有终端节点?或者还有其他办法吗?
注意:语法可能是错误的,这是我为这个问题发明的。请略读一下。
"ContentAssist"(在术语"代码完成"下更为人所知)的实现是一项不平凡的任务,您可能必须深入挖掘ANTLR的内部类(至少是atm)。您要做的是遍历由ANTLR为每个解析器和lexer类生成的ATN。博客文章中描述了一种方法:为基于ANTLR的编辑器构建自动补全。LL1Analyzer也使用了类似的方法,它是ANTLR运行时中的一个类。
然而,两者都只能给你lexer令牌(例如,你的所有关键字+其他关键字,如IDENTIFIER或DIGIT)。这意味着你不会得到例如变量引用之类的。