Java 如何使用ANTLR中的贪婪=false选项访问匹配的属性文本块?
我的ANTLR语法中有这样一条规则:Java 如何使用ANTLR中的贪婪=false选项访问匹配的属性文本块?,java,antlr,grammar,greedy,non-greedy,Java,Antlr,Grammar,Greedy,Non Greedy,我的ANTLR语法中有这样一条规则: COMMENT : '/*' (options {greedy=false;} : . )* '*/' ; COMMENT : '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text); 此规则只匹配c风格的注释,因此它将接受任意一对/*和*/以及任意文本,并且工作正常 我现在要做的是,当规则匹配时,捕获/*和*/之间的所有文本,使其可供操
COMMENT : '/*' (options {greedy=false;} : . )* '*/' ;
COMMENT : '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text);
此规则只匹配c风格的注释,因此它将接受任意一对/*和*/以及任意文本,并且工作正常
我现在要做的是,当规则匹配时,捕获/*和*/之间的所有文本,使其可供操作访问。大概是这样的:
COMMENT : '/*' (options {greedy=false;} : . )* '*/' ;
COMMENT : '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text);
这种方法不起作用,在解析过程中,当到达“/”后面的第一个字符时,它会给出“没有可行的替代方案”
我不太清楚是否/如何做到这一点-欢迎提供任何建议或指导,谢谢。尝试以下方法:
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);} )* '*/';
试试这个:
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);} )* '*/';
请注意,您可以简单地执行以下操作:
getText().substring(2, getText().length()-2)
在注释上
,因为第一个和最后两个字符始终是/*
和*/
您还可以删除选项{greedy=false;}:
,因为*
和+
都是不冻结的(尽管没有
它们是贪婪的)(i)
编辑
或者在注释
标记上使用setText(…)
立即丢弃/*
和*/
。一个小演示:
文件T.g
:
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();}
;
语法T;
@解析器::成员{
公共静态void main(字符串[]args)引发异常{
AntlStringStream in=新的AntlStringStream(
“/*abc*/\n”+
“\n”+
“/*\n”+
“DEF\n”+
"*/ "
);
TLexer lexer=新的TLexer(in);
CommonTokenStream令牌=新的CommonTokenStream(lexer);
TParser parser=新的TParser(令牌);
parser.parse();
}
}
作语法分析
:(注释{System.out.printf(“已解析::>\%s请注意,您只需执行以下操作:
getText().substring(2, getText().length()-2)
在注释上
,因为第一个和最后两个字符始终是/*
和*/
您还可以删除选项{greedy=false;}:
,因为*
和+
都是不冻结的(尽管没有
它们是贪婪的)(i)
编辑
或者在注释
标记上使用setText(…)
立即丢弃/*
和*/
。一个小演示:
文件T.g
:
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();}
;
语法T;
@解析器::成员{
公共静态void main(字符串[]args)引发异常{
AntlStringStream in=新的AntlStringStream(
“/*abc*/\n”+
“\n”+
“/*\n”+
“DEF\n”+
"*/ "
);
TLexer lexer=新的TLexer(in);
CommonTokenStream令牌=新的CommonTokenStream(lexer);
TParser parser=新的TParser(令牌);
parser.parse();
}
}
作语法分析
:(注释{System.out.printf(“已解析::>\%s