我在ANTLR中编写语法,将Java源文件解析为AST以供以后分析。与其他解析器(如JavaDoc)不同,我试图保留所有注释。这很困难的注释可以在代码中的任何地方使用。如果注释在源代码中某处与语法不匹配,则ANTLR无法完成对文件的解析。
有没有办法让ANTLR自动添加它找到的任何评论到AST?我知道词法分析器可以使用{skip();}
或通过将文本发送到隐藏通道来忽略所有注释。无论设置了哪个选项,ANTLR都可以毫无问题地解析文件。
欢迎任何想法。
答案 0 :(得分:7)
有没有办法让ANTLR自动添加它找到的任何评论到AST?
不,您必须使用额外的comments
规则来填充整个语法,以便考虑所有有效地点的评论:
...
if_stat
: 'if' comments '(' comments expr comments ')' comments ...
;
...
comments
: (SingleLineComment | MultiLineComment)*
;
SingleLineComment
: '//' ~('\r' | '\n')*
;
MultiLineComment
: '/*' .* '*/'
;
答案 1 :(得分:7)
最终Antlr 4参考中的第12.1节显示了如何访问注释而无需在整个语法中使用注释规则。简而言之,您将其添加到语法文件中:
grammar Java;
@lexer::members {
public static final int WHITESPACE = 1;
public static final int COMMENTS = 2;
}
然后,对于您的评论规则,请执行以下操作:
COMMENT
: '/*' .*? '*/' -> channel(COMMENTS)
;
LINE_COMMENT
: '//' ~[\r\n]* -> channel(COMMENTS)
;
然后在您的代码中通过getHiddenTokensToLeft / getHiddenTokensToRight询问令牌,并查看书中的12.1部分,您将看到如何执行此操作。
答案 2 :(得分:4)
首先:将所有评论指向某个频道(仅限评论)
COMMENT
: '/*' .*? '*/' -> channel(2)
;
LINE_COMMENT
: '//' ~[\r\n]* -> channel(2)
;
第二:打印出所有评论
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
for (int index = 0; index < tokens.size(); index++)
{
Token token = tokens.get(index);
// substitute whatever parser you have
if (token.getType() != Parser.WS)
{
String out = "";
// Comments will be printed as channel 2 (configured in .g4 grammar file)
out += "Channel: " + token.getChannel();
out += " Type: " + token.getType();
out += " Hidden: ";
List<Token> hiddenTokensToLeft = tokens.getHiddenTokensToLeft(index);
for (int i = 0; hiddenTokensToLeft != null && i < hiddenTokensToLeft.size(); i++)
{
if (hiddenTokensToLeft.get(i).getType() != IDLParser.WS)
{
out += "\n\t" + i + ":";
out += "\n\tChannel: " + hiddenTokensToLeft.get(i).getChannel() + " Type: " + hiddenTokensToLeft.get(i).getType();
out += hiddenTokensToLeft.get(i).getText().replaceAll("\\s", "");
}
}
out += token.getText().replaceAll("\\s", "");
System.out.println(out);
}
}
答案 3 :(得分:0)
我在lexer部分做到了这一点:
WS : ( [ \t\r\n] | COMMENT) -> skip
;
fragment
COMMENT
: '/*'.*'*/' /*single comment*/
| '//'~('\r' | '\n')* /* multiple comment*/
;
就像它会自动删除它们一样!
答案 4 :(得分:0)
功能&#34;岛语法&#34;也可以使用。请参阅ANTLR4书中的以下部分:
Island Grammars:在同一文件中处理不同的格式
答案 5 :(得分:0)
对于ANTLR v3:
空格标记通常不由解析器处理,但它们仍然在HIDDEN通道上捕获。
如果您使用BufferedTokenStream
,则可以通过它获取所有令牌的列表并进行后处理,并根据需要添加它们。