我的ANTLR语法中有一条规则:
COMMENT : '/*' (options {greedy=false;} : . )* '*/' ;
此规则只是匹配c风格的注释,因此它将接受任意一对/ *和* /以及介于两者之间的任意文本,并且它可以正常工作。
我现在要做的是在规则匹配时捕获/ *和* /之间的所有文本,以使其可以被操作访问。像这样:
COMMENT : '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text);
这种方法不起作用,在解析过程中,在到达“/ *”之后的第一个字符时给出“没有可行的选择”
我不清楚是否/如何做到这一点 - 欢迎任何建议或指导,谢谢。
答案 0 :(得分:4)
请注意,您只需执行以下操作:
getText().substring(2, getText().length()-2)
<{1>} token上的,因为第一个和最后两个字符始终为COMMENT
和/*
。
您也可以删除*/
,因为options {greedy=false;} :
和.*
都不合适(尽管没有.+
他们 贪婪)(i )。
或者使用.
令牌上的setText(...)
立即放弃Comment
和/*
。一个小小的演示:
档案*/
:
T.g
然后生成一个解析器&amp; lexer,编译所有.java文件并运行包含main方法的解析器:
java -cp antlr-3.2.jar org.antlr.Tool T.g javac -cp antlr-3.2.jar *.java java -cp .:antlr-3.2.jar TParser (or `java -cp .;antlr-3.2.jar TParser` on Windows)
将产生以下输出:
grammar T;
@parser::members {
public static void main(String[] args) throws Exception {
ANTLRStringStream in = new ANTLRStringStream(
"/* abc */ \n" +
" \n" +
"/* \n" +
" DEF \n" +
"*/ "
);
TLexer lexer = new TLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TParser parser = new TParser(tokens);
parser.parse();
}
}
parse
: ( Comment {System.out.printf("parsed :: >\%s<\%n", $Comment.getText());} )+ EOF
;
Comment
: '/*' .* '*/' {setText(getText().substring(2, getText().length()-2));}
;
Space
: (' ' | '\t' | '\r' | '\n') {skip();}
;
(i)The Definitive ANTLR Reference,第4章,扩展的BNF子规则,第86页。
答案 1 :(得分:1)
试试这个:
COMMENT :
'/*' {StringBuilder comment = new StringBuilder();} ( options {greedy=false;} : c=. {comment.appendCodePoint(c);} )* '*/' {System.out.println(comment.toString());};
另一种实际返回StringBuilder对象的方法,以便您可以在程序中使用它:
COMMENT returns [StringBuilder comment]:
'/*' {comment = new StringBuilder();} ( options {greedy=false;} : c=. {comment.append((char)c);} )* '*/';