0

我的 ANTLR 语法中有这样的规则:

COMMENT :  '/*' (options {greedy=false;} : . )* '*/' ;

此规则仅匹配 c 样式的注释,因此它可以接受任何一对 /* 和 */ 以及介于两者之间的任意文本,并且它工作正常。

我现在要做的是在规则匹配时捕获 /* 和 */ 之间的所有文本,以使其可供操作访问。像这样的东西:

COMMENT :  '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text);

这种方法不起作用,在解析过程中它在到达“/ *”之后的第一个字符时给出“没有可行的选择”

我不太清楚是否/如何做到这一点 - 欢迎任何建议或指导,谢谢。

4

2 回答 2

4

请注意,您可以简单地执行以下操作:

getText().substring(2, getText().length()-2)

COMMENT 令牌上,因为第一个和最后两个字符将始终是/*and */

您也可以删除,options {greedy=false;} :因为两者.*都是不贪婪.+的(尽管没有.它们贪婪的)(i)。

编辑

setText(...)Comment令牌上使用以立即丢弃/*and */。一个小演示:

文件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();}
  ;

然后生成解析器和词法分析器,编译所有 .java 文件并运行包含 main 方法的解析器:

java -cp antlr-3.2.jar org.antlr.Tool Tg
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar TParser
  (或 Windows 上的 `java -cp .;antlr-3.2.jar TParser`)

这将产生以下输出:

parsed :: > abc <
parsed :: >          
   DEF      
<

(i)权威 ANTLR 参考,第 4 章,扩展 BNF 子规则,第 86 页。

于 2011-01-13T08:23:25.787 回答
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);} )* '*/';
于 2011-01-13T05:22:54.507 回答