Antlr 如何标记块(注释、字符串等)以及块间(块外的任何字符)?

Antlr 如何标记块(注释、字符串等)以及块间(块外的任何字符)?,antlr,antlr4,lexer,Antlr,Antlr4,Lexer,我需要标记所有“在”任何评论之外的内容,直到行尾。例如: take me */ and me /* but not me! */ I'm in! // I'm not... 标记为(STR是“外部”字符串,BC是块注释,LC是单行注释): 以及: 标记为: { BC : " starting with don't take me ", STR: " ...take me..." } 问题是STR可以是除注释之外的任何,并且由于注释开头不是单字符标记,我不能对STR使用否定规则

我需要标记所有“在”任何评论之外的内容,直到行尾。例如:

take me */ and me /* but not me! */ I'm in! // I'm not...
标记为(
STR
是“外部”字符串,
BC
是块注释,
LC
是单行注释):

以及:

标记为:

{
    BC : " starting with don't take me ",
    STR: " ...take me..."
}
问题是
STR
可以是除注释之外的任何,并且由于注释开头不是单字符标记,我不能对
STR
使用否定规则

我想也许可以做一些类似的事情:

STR : { IsNextSequenceTerminatesThe_STR_rule(); }?;
但我不知道如何在lexer actions中寻找角色


甚至可以用ANTLR4 lexer实现吗?如果可以,那么如何实现呢?

试试下面的方法:

grammar T;

@lexer::members {

  // Returns true iff either "//" or "/*"  is ahead in the char stream.
  boolean startCommentAhead() {
    return _input.LA(1) == '/' && (_input.LA(2) == '/' || _input.LA(2) == '*');
  }
}

// other rules

STR
 : ( {!startCommentAhead()}? . )+
 ;

是的,可以执行您正在尝试的标记化

基于上述内容,您需要嵌套注释。这些只能在lexer中实现,而无需操作、谓词或任何代码。为了有嵌套的注释,如果不使用贪婪/非贪婪的ANTLR选项,就更容易了。您需要将其指定/编码到lexer语法中。下面是你需要的三条lexer规则。。。使用STR定义

我添加了一个用于测试的解析器规则。我还没有测试过这个,但它应该能做你提到的所有事情。此外,它不仅限于“行尾”,如果需要,您可以进行修改

/*
    All 3 COMMENTS are Mutually Exclusive
 */
DOC_COMMENT
        : '/**'
          ( [*]* ~[*/]         // Cannot START/END Comment
            ( DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            | .
            )*?
          )?
          '*'+ '/' -> channel( DOC_COMMENT )
        ;
BLK_COMMENT
        : '/*'
          (
            ( /* Must never match an '*' in position 3 here, otherwise
                 there is a conflict with the definition of DOC_COMMENT
               */
              [/]? ~[*/]       // No START/END Comment
            | DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            )
            ( DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            | .
            )*?
          )?
          '*/' -> channel( BLK_COMMENT )
        ;
INL_COMMENT
        : '//'
          ( ~[\n\r*/]          // No NEW_LINE
          | INL_COMMENT        // Nested Inline Comment
          )* -> channel( INL_COMMENT )
        ;
STR       // Consume everthing up to the start of a COMMENT
        : ( ~'/'      // Any Char not used to START a Comment
          | '/' ~[*/] // Cannot START a Comment
          )+
        ;

start
        : DOC_COMMENT
        | BLK_COMMENT
        | INL_COMMENT
        | STR
        ;
grammar T;

@lexer::members {

  // Returns true iff either "//" or "/*"  is ahead in the char stream.
  boolean startCommentAhead() {
    return _input.LA(1) == '/' && (_input.LA(2) == '/' || _input.LA(2) == '*');
  }
}

// other rules

STR
 : ( {!startCommentAhead()}? . )+
 ;
/*
    All 3 COMMENTS are Mutually Exclusive
 */
DOC_COMMENT
        : '/**'
          ( [*]* ~[*/]         // Cannot START/END Comment
            ( DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            | .
            )*?
          )?
          '*'+ '/' -> channel( DOC_COMMENT )
        ;
BLK_COMMENT
        : '/*'
          (
            ( /* Must never match an '*' in position 3 here, otherwise
                 there is a conflict with the definition of DOC_COMMENT
               */
              [/]? ~[*/]       // No START/END Comment
            | DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            )
            ( DOC_COMMENT
            | BLK_COMMENT
            | INL_COMMENT
            | .
            )*?
          )?
          '*/' -> channel( BLK_COMMENT )
        ;
INL_COMMENT
        : '//'
          ( ~[\n\r*/]          // No NEW_LINE
          | INL_COMMENT        // Nested Inline Comment
          )* -> channel( INL_COMMENT )
        ;
STR       // Consume everthing up to the start of a COMMENT
        : ( ~'/'      // Any Char not used to START a Comment
          | '/' ~[*/] // Cannot START a Comment
          )+
        ;

start
        : DOC_COMMENT
        | BLK_COMMENT
        | INL_COMMENT
        | STR
        ;