ANTLR:消除杂波

ANTLR:消除杂波,antlr,antlr3,Antlr,Antlr3,我现在正在学习ANTLR。比方说,我有一个VHDL代码,希望对进程块进行一些处理。其余的应该完全忽略。我不想描述整个VHDL语言,因为我只对进程块感兴趣。所以我可以编写一个匹配进程块的规则。但是我如何告诉ANTLR只匹配进程块规则而忽略任何其他内容呢?我几乎不知道VHDL,所以假设您想用多行注释替换Java源文件中的所有单行注释: //foo 应成为: /* foo */ 当然,您需要让lexer匹配单行注释。但您还应确保它能够识别多行注释,因为您不希望//栏在以下情况下被识别为单行注释:

我现在正在学习ANTLR。比方说,我有一个VHDL代码,希望对进程块进行一些处理。其余的应该完全忽略。我不想描述整个VHDL语言,因为我只对进程块感兴趣。所以我可以编写一个匹配进程块的规则。但是我如何告诉ANTLR只匹配进程块规则而忽略任何其他内容呢?

我几乎不知道VHDL,所以假设您想用多行注释替换Java源文件中的所有单行注释:

//foo
应成为:

/* foo */
当然,您需要让lexer匹配单行注释。但您还应确保它能够识别多行注释,因为您不希望//栏在以下情况下被识别为单行注释:

/*
//bar
*/
字符串文字也是如此:

String s = "no // comment";
最后,您应该在lexer中创建某种类型的catch-all规则,以匹配任何字符

快速演示:

grammar T;

parse
 : (t=. {System.out.print($t.text);})* EOF
 ;

Str
 : '"' ('\\' . | ~('\\' | '"'))* '"'
 ;

MLComment
 : '/*' .* '*/'
 ;

SLComment
 : '//' ~('\r' | '\n')*
   {
     setText("/* " + getText().substring(2) + " */");
   }
 ;

Any
 : . // fall through rule, matches any character
 ;
如果您现在像这样解析输入:

//comment 1
class Foo {

  //comment 2

  /* 
   * not // a comment
   */
  String s = "not // a // comment"; //comment 3
}
以下内容将打印到您的控制台:

/* comment 1 */
class Foo {

  /* comment 2 */

  /* 
   * not // a comment
   */
  String s = "not // a // comment"; /* comment 3 */
}

请注意,这只是一个快速演示:Java中的字符串文字可能包含Unicode转义,我的演示不支持这种转义,我的演示也不处理字符文字char literal char c='';我会打破它。当然,所有这些问题都很容易解决。

我几乎不知道VHDL,所以假设您想用多行注释替换Java源文件中的所有单行注释:

//foo
应成为:

/* foo */
当然,您需要让lexer匹配单行注释。但您还应确保它能够识别多行注释,因为您不希望//栏在以下情况下被识别为单行注释:

/*
//bar
*/
字符串文字也是如此:

String s = "no // comment";
最后,您应该在lexer中创建某种类型的catch-all规则,以匹配任何字符

快速演示:

grammar T;

parse
 : (t=. {System.out.print($t.text);})* EOF
 ;

Str
 : '"' ('\\' . | ~('\\' | '"'))* '"'
 ;

MLComment
 : '/*' .* '*/'
 ;

SLComment
 : '//' ~('\r' | '\n')*
   {
     setText("/* " + getText().substring(2) + " */");
   }
 ;

Any
 : . // fall through rule, matches any character
 ;
如果您现在像这样解析输入:

//comment 1
class Foo {

  //comment 2

  /* 
   * not // a comment
   */
  String s = "not // a // comment"; //comment 3
}
以下内容将打印到您的控制台:

/* comment 1 */
class Foo {

  /* comment 2 */

  /* 
   * not // a comment
   */
  String s = "not // a // comment"; /* comment 3 */
}

请注意,这只是一个快速演示:Java中的字符串文字可能包含Unicode转义,我的演示不支持这种转义,我的演示也不处理字符文字char literal char c='';我会打破它。当然,所有这些问题都很容易解决。

在即将推出的ANTLR v4中,您可以进行模糊解析。看看

您可以在此处获得测试版软件:


Terence

在即将推出的ANTLR v4中,您可以进行模糊解析。看看

您可以在此处获得测试版软件:


特伦斯

谢谢!ANTLR真是一部伟大的作品!你的书也很棒!非常感谢。ANTLR真是一部伟大的作品!你的书也很棒!谢谢你,巴特。我想知道是否有可能用符合任何规则的ANTLR数据捕获?比如说,我想捕获两个SLComment标记之间的所有文本,这怎么可能呢?谢谢@Bart。我想知道是否有可能用符合任何规则的ANTLR数据捕获?比如说,我想捕获两个SLComment标记之间的所有文本,怎么可能呢?